From: Jan Svitok Date: 2007-02-05T19:19:47+09:00 Subject: Re: Exception never raised when threading an eval containing a malformed command [might be a bug ?] On 2/5/07, Benjamin Babut wrote: > > Hello everyone! > > I've encountered a strange issue when coding a tool extending ruby, and > was wondering if I was missing something... I'm working under windows with > the last stable release of ruby (1.8.5-21) and did not find a way to debug > ruby sources to observe the behaviour. This is reproductible with just the > common ruby interpreter. Let me explain the problem : > > First let's consider this small script : > > #!/usr/bin/env ruby > $FOO+2 > > We get the evident result ($FOO is not defined, an exception's raised) : > > test.rb:2: undefined method `+' for nil:NilClass (NoMethodError) > > Then let's consider this small script : > > #!/usr/bin/env ruby > eval("puts \"foo") > > You can see that the string given to puts is malformed, so we get again an > exception : > > (eval):1: compile error (SyntaxError) > (eval):1: unterminated string meets end of file > > Ok. Now let's thread this. Let's consider the following script : > > #!/usr/bin/env ruby > def newthread() > toret = Thread.new { > puts "START" > begin > $FOO+2 > rescue > puts("EXCEPTION !!!!!!!!") > end > puts "END" > } > return toret > end > > $TESTTHREAD = newthread() > 2.times { > if(!$TESTTHREAD.alive?) then > puts "DEAD, RESURRECTING" > $TESTTHREAD = newthread() > sleep(4) > end > } > > We create a thread, provoke an exception, catch it, restart the thread, > and so on twice again. We get the following expected behaviour : > > START > EXCEPTION !!!!!!!! > END > DEAD, RESURRECTING > START > EXCEPTION !!!!!!!! > END > DEAD, RESURRECTING > START > EXCEPTION !!!!!!!! > END > > But now, let's consider this (here comes the issue) : we do exactly the > same thing (we only replace the $FOO+2 line by our malformed eval-puts) : > > #!/usr/bin/env ruby > def newthread() > toret = Thread.new { > puts "START" > begin > eval("puts \"foo") > rescue > puts("EXCEPTION !!!!!!!!") > end > puts "END" > } > return toret > end > > $TESTTHREAD = newthread() > 2.times { > if(!$TESTTHREAD.alive?) then > puts "DEAD, RESURRECTING" > $TESTTHREAD = newthread() > sleep(4) > end > } > > And then we get... > > START > DEAD, RESURRECTING > START > DEAD, RESURRECTING > START > > (!!) It simply seems that the ruby thread dies inside the eval, and the > exception is never raised (?). Has someone an explanation for this ? > (found a bug somewhere ?) :) > > Many thanks by advance for those who'd work on that matter! Hi, it's easy: $FOO+2 raises NoMethodError < StandardError while eval(..) raises SyntaxError !< StandardError empty rescue == rescue StandardError If you want to catch ALL exceptions, use rescue Exception. For exceptions hierarchy see http://www.zenspider.com/Languages/Ruby/QuickRef.html#34