diff --git a/CHANGELOG.md b/CHANGELOG.md index 30a47043..4cc5fe07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Unreleased ### Changed/Added +- Prevent warnings on Ruby 3.1 if finalizer is called twice [TODO](https://github.com/roo-rb/roo/pull/TODO) ## [2.10.0] 2023-02-07 diff --git a/lib/roo/tempdir.rb b/lib/roo/tempdir.rb index 4be755b7..7ad79890 100644 --- a/lib/roo/tempdir.rb +++ b/lib/roo/tempdir.rb @@ -4,7 +4,10 @@ def finalize_tempdirs(object_id) if @tempdirs && (dirs_to_remove = @tempdirs[object_id]) @tempdirs.delete(object_id) dirs_to_remove.each do |dir| - ::FileUtils.remove_entry(dir) + # Pass force=true to avoid an exception (and thus warnings in Ruby 3.1) if dir has + # already been removed. This can occur when the finalizer is called both in a forked + # child process and in the parent. + ::FileUtils.remove_entry(dir, true) end end end diff --git a/test/helpers/test_accessing_files.rb b/test/helpers/test_accessing_files.rb index 8732bc88..bd31b634 100644 --- a/test/helpers/test_accessing_files.rb +++ b/test/helpers/test_accessing_files.rb @@ -36,6 +36,27 @@ def test_finalize end end + def test_finalize_twice + skip if defined? JRUBY_VERSION + + instance = Class.new { include Roo::Tempdir }.new + + tempdir = instance.make_tempdir(instance, "my_temp_prefix", nil) + assert File.exist?(tempdir), "Expected #{tempdir} to initially exist" + + pid = Process.fork do + # Inside the forked process finalize does not affect the parent process, but does delete the + # tempfile on disk + instance.finalize_tempdirs(instance.object_id) + end + + Process.wait(pid) + refute File.exist?(tempdir), "Expected #{tempdir} to have been cleaned up by child process" + + instance.finalize_tempdirs(instance.object_id) + refute File.exist?(tempdir), "Expected #{tempdir} to still have been cleaned up" + end + def test_cleanup_on_error # NOTE: This test was occasionally failing because when it started running # other tests would have already added folders to the temp directory,