# Exceptions occassionally lost by child threads

**URL:** <https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605>\
**Category:** Ruby\
**Created:** [March 30, 2007, 7:06am UTC](https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605 "2007-03-30T07:06:49Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![soroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/f9ae1b/32.png) [@soroe](https://www.ruby-forum.com/u/soroe)\
**Post date:** [March 30, 2007, 7:06am UTC](https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605/1 "2007-03-30T07:06:49Z")

</div>

Hey Guys,

As I understand it, the correct way to pass exceptions between threads  
is to explicitly raise them in the target thread… so something like  
this works:

a = Thread.new(Thread.current) { |parent|  
…  
parent.raise err

}

What I’m curious about is that the following code also seems to work:

a = Thread.new {  
begin  
puts ‘blue’  
sleep 2;  
raise ArgumentError.new(‘green’)  
rescue Exception =\> err  
puts “Caught: #{err.message}”  
raise err  
end  
}

begin  
while a  
sleep 1  
a = a.join(1)  
end  
puts ‘yellow’  
rescue Exception =\> err  
puts “Caught it again: #{err.message}”  
end

#blue  
#Caught: green  
#Caught it again: green

However, if i move the sleep 1 statement to after a = a.join(1), the  
exception seems to get lost and the output is:

#blue  
#Caught: green  
#yellow

Should exceptions automatically propagate from children up to the  
parent? And if so, why should the positioning of something as innocuous  
as sleep 1 matter?

Sonny.

---

<div class="post-metadata">

**Author:** ![soroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/f9ae1b/32.png) [@soroe](https://www.ruby-forum.com/u/soroe)\
**Post date:** [March 30, 2007, 9:20am UTC](https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605/2 "2007-03-30T09:20:29Z")

</div>

> Should exceptions automatically propagate from children up to the  
> parent? And if so, why should the positioning of something as innocuous  
> as sleep 1 matter?  
> Because you have a timeout on the join (a.join(1))

In the first case it sleeps one second, and waits for ‘a’ to finish. It  
works if ‘a’ raises within two seconds. Note that it could also fail  
since ‘sleep’ is not perfect and it is possible for the main thread to  
reach the timeout on ‘join’ before ‘a’ raises.

In the second case, the main thread only waits ‘a’ for one second. It is  
useless because of the sleep(2) in ‘a’.

It should work as expected if you replace a.join(1) by a.join

---

<div class="post-metadata">

**Author:** ![soroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/f9ae1b/32.png) [@soroe](https://www.ruby-forum.com/u/soroe)\
**Post date:** [March 30, 2007, 6:55pm UTC](https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605/3 "2007-03-30T18:55:39Z")

</div>

Thanks guys. My bad. For some reason I thought join(1) returned nil  
when the thread completed. That should learn me to post messages when  
I’m half asleep:"P

In the following snippet the parent always catches the exception  
regardless of the position of the sleep 1 statment.

a = Thread.new {  
begin  
puts ‘blue’  
sleep 2;  
raise ArgumentError.new(‘green’)  
rescue Exception =\> err  
puts “Caught: #{err.message}”  
raise err  
end  
}

begin  
b = a  
while a  
sleep 1 # position 1  
b = a.join(1)  
a = b if !a  
sleep 1 # position 2  
end  
puts ‘yellow’  
rescue Exception =\> err  
puts “Caught it again: #{err.message}”  
end

---

<div class="post-metadata">

**Author:** ![soroe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/f9ae1b/32.png) [@soroe](https://www.ruby-forum.com/u/soroe)\
**Post date:** [March 30, 2007, 10:00am UTC](https://www.ruby-forum.com/t/exceptions-occassionally-lost-by-child-threads/90605/4 "2007-03-30T10:00:34Z")

</div>

On 30.03.2007 09:19, Sylvain J. wrote:

> In the second case, the main thread only waits ‘a’ for one second. It is  
> useless because of the sleep(2) in ‘a’.
> 
> It should work as expected if you replace a.join(1) by a.join

It seems to be a property of Thread#join and #value that they will  
automatically propagate any uncaught exceptions of the the joined  
thread:

irb(main):003:0\> t=Thread.new { sleep 20; raise “Foo” }  
=\> #\<Thread:0x7ef7ef6c sleep\>  
irb(main):004:0\> begin; t.join; rescue Exception =\> e; p e; end  
#\<RuntimeError: Foo\>  
=\> nil

I think this behavior is documented, although a bit cryptic IMHO:

“If thr had previously raised an exception and the abort\_on\_exception  
and $DEBUG flags are not set (so the exception has not yet been  
processed) it will be processed at this time.”  
[http://www.ruby-doc.org/core/classes/Thread.html#M000474](http://www.ruby-doc.org/core/classes/Thread.html#M000474)

Kind regards

robert
