Ruby: rescue doesn't rescue from thread

826 views Asked by At
Thread.abort_on_exception = true

begin
    #code in this block doesn't matter at all, it just needs to produce errors.
    [1, 2].each do |i|
        a = Thread.new do
            errory
        end
    end 
    a.join 
rescue Exception
    puts 'error!'
end

raises /home/lakesare/Desktop/multithreading/test.rb:6:in 'block (2 levels) in <main>': undefined local variable or method 'errory' for main:Object (NameError) instead of returning error! for some reason.
If Thread.new {} isn't wrapped in each {}, block is rescued properly.
Why is that? How to rescue my thread properly in this case?

edit: I found wrapping begin-rescue-end block in identical block helps. But one question lingers - why isn't one rescue enough?

edit: wrapping in another rescue block helps, but not always - sometimes it still doesn't rescue.

1

There are 1 answers

0
Rich Drummond On BEST ANSWER

There are a few problems with what you have written that I think are clouding the issue for you.

  1. You shouldn’t set Thread.abort_on_exception = true unless you really want your program to abort when an exception occurs in a secondary thread. Typically, you’d only want this set to true for debugging. If set to false, any exception raised in a thread will cause that thread to exit but will only be visible to the parent thread when you join with the child thread.

  2. In your code above, when you attempt to join with a thread, the variable a is out of scope. Thus you should get a NameError there too.

  3. Even if this were in scope, you are only joining with one of your threads.

You should find the following more predictable:

Thread.abort_on_exception = false

begin
  threads = [1, 2].collect do |i|
    Thread.new do
      errory
    end
  end
  threads.each { |thread| thread.join } # You might want to use a ThreadsWait here instead.
rescue Exception
  puts 'error!'
end