Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unlink Tempfiles after use in SpawnProcess #926

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

mvz
Copy link
Contributor

@mvz mvz commented Apr 1, 2024

Summary

Explictly call #unlink on Tempfiles used in SpawnProcess, instead of waiting for the finalizer.

Details

Adds a call to #unlink right after reading the Tempfile and storing the contents in a variable.

Motivation and Context

On Windows, the finalizer for Tempfile will raise an error if Errno::ENOACCES is raised when removing the file. However, if this happens when #unlink is called, the error is caught.

This change calls #unlink on the Tempfiles that are used to store the output of spawned processes. This means the finalizer will not need to unlink the file, so any Errno::ENOACCES errors during unlinking will be caught.

The raised errors did not make any specs fail, but they did appear in the rspec output.

How Has This Been Tested?

I ran the specs. In CI, we will see if the backtraces are gone.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Internal change (refactoring, test improvements, developer experience or update of dependencies)

Checklist:

  • I've added tests for my code
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

mvz added 2 commits April 1, 2024 21:28
On Windows, the finalizer for Tempfile will raise an error if
Errno::ENOACCES is raised when removing the file. However, if this
happens when #unlink is called, the error is caught.

This change calls #unlink on the Tempfiles that are used to store the
output of spawned processes. This means the finalizer will not need to
unlink the file, so any Errno::ENOACCES errors during unlinking will be
caught.

The raised errors did not make any specs fail, but they did appear in
the rspec output.
@mvz
Copy link
Contributor Author

mvz commented Apr 1, 2024

Good theory but this doesn't help 😞

@mvz mvz force-pushed the unlink-tmpfiles branch from fbe0507 to e35a0fa Compare April 1, 2024 20:54
@mvz
Copy link
Contributor Author

mvz commented Apr 1, 2024

Here's the #unlink method, and it is now clear why this PR doesn't help:

  def unlink
    return if @unlinked
    begin
      File.unlink(@tmpfile.path)
    rescue Errno::ENOENT
    rescue Errno::EACCES
      # may not be able to unlink on Windows; just ignore
      return
    end
    ObjectSpace.undefine_finalizer(self)
    @unlinked = true
  end

If unlink fails due to Errno::EACCES, the finalizer is not removed, and that finalizer will try again to unlink the Tempfile. As a result, Errno::EACCES errors will still occur there and cause backtraces to be printed.

This method also has the following comment:

  # However, unlink-before-close may not be supported on non-POSIX operating
  # systems. Microsoft Windows is the most notable case: unlinking a non-closed
  # file will result in an error, which this method will silently ignore. If
  # you want to practice unlink-before-close whenever possible, then you should
  # write code like this:

So the Errno::EACCES error is expected to come from the Tempfile still being open.

@olleolleolle
Copy link
Contributor

(Good investigation!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants