Issue #13876 has been updated by jeremyevans0 (Jeremy Evans).


This is still a problem in the master branch.  Possible solutions:

1. Run finalizers in a separate thread instead of the main thread.
2. Mark when thread is running finalizers. Mark exceptions added by `Thread#raise`.  When a thread is checking pending interrupts, if it is running finalizers, ignore interrupts added by `Thread#raise`, so that the delivery of the exceptions is delayed until the thread is no longer running finalizers.
3. Mark when thread is running finalizers.  Do not check for pending interrupts when running finalizers.
4. Remove `Thread#raise`.

Option 4 is the simplest to implement, but it is not backwards compatible and I don't think it would be acceptable.

I've a pull request for option 3, since it was fairly simple to implement: https://github.com/ruby/ruby/pull/4366

I think that the option 1 would be the most robust approach, but it requires an extra thread.

----------------------------------------
Bug #13876: Tempfile's finalizer can be interrupted by a Timeout exception which can cause the process to hang
https://bugs.ruby-lang.org/issues/13876#change-91365

* Author: jrafanie (Joe Rafaniello)
* Status: Open
* Priority: Normal
* ruby -v: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15]
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
Ruby hangs if a Timeout is raised when a Tempfile's finalizer is run.

This also happens on ruby 2.3.4 on OSX.  I could only recreate this on linux once but not reliably.  Maybe the finalizer runs at a different and unpredictable time on Linux.

See the following script:

```ruby
require 'tempfile'
require 'timeout'
Tempfile.new("x")

# this empty method is needed for some reason, maybe scope/GC related
def stuff
  ""
end

2.times do |i|
  begin
    Timeout.timeout(1e-9) do
      loop do
        begin
          "result"
        ensure
        end
      end
    end
  rescue Timeout::Error
  end
end
```

When run, I get the following output and it hangs ~4 out of 5 times on OSX:

```
$ ruby -d test.rb
Exception `LoadError' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/rubygems.rb:1345 - cannot load such file -- rubygems/defaults/operating_system
Exception `LoadError' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/rubygems.rb:1354 - cannot load such file -- rubygems/defaults/ruby
removing /var/folders/fq/blrz820d3qz7nm7vj8mbtfs40000gq/T/x20170906-72981-1ttdgpr...
<HANGS>
```

When it doesn't hang (~1 in 5 tries), it looks like this (the exception seems to be raised after the file cleanup is done):

```
$ ruby -d test.rb
Exception `LoadError' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/rubygems.rb:1345 - cannot load such file -- rubygems/defaults/operating_system
Exception `LoadError' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/rubygems.rb:1354 - cannot load such file -- rubygems/defaults/ruby
removing /var/folders/fq/blrz820d3qz7nm7vj8mbtfs40000gq/T/x20170906-72963-164cw8j...
done
Exception `Timeout::Error' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/timeout.rb:114 - execution expired
Exception `Timeout::Error' at /Users/joerafaniello/.rubies/ruby-2.4.1/lib/ruby/2.4.0/timeout.rb:114 - execution expired
```

When it hangs, it seems to be this code:
https://github.com/ruby/ruby/blob/0f25c6d7d59ff9744d1ca5dc908cc12c8ce79e25/lib/tempfile.rb#L253-L261







-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>