Swallowed exceptions

49 views
Skip to first unread message

Or Cohen

unread,
Oct 27, 2013, 5:40:54 AM10/27/13
to openwfe...@googlegroups.com
Hi,

I've stumbled upon an issue which I'm not sure how to even address it.
If I raise a RuntimeError (simple raise) or a StandardError (specifically) from a participant then the flow behaves fine, i.e. I see the exception with #noisy and I can catch it with :on_error.
But if I raise a NameError, on some cases it just waits forever.

I'm working on a big project so at first I thought it was something related to the project's code, but I've managed to create a simple example that causes this (using latest master).

require 'ruote'
require 'ruote/storage/fs_storage'
 
ruote = Ruote::Dashboard.new(
  Ruote::Worker.new(
    Ruote::FsStorage.new('ruote_work')))

class PartA < Ruote::Participant
  def on_workitem
    raise NameError, self.class
    reply # Not really needed
  end
end

class PartB < Ruote::Participant
  def on_workitem
    raise StandardError, self.class
    reply # Not really needed
  end
end

class HandleError < Ruote::Participant
  def on_workitem
    puts workitem.param_or_field('msg')
    reply
  end
end

ruote.register 'part_a', PartA
ruote.register 'part_b', PartB
ruote.register 'handle_error', HandleError

pdef = Ruote.define do
  concurrence do
    part_a :on_error => 'handle error'
    part_b :on_error => 'handle error'
  end

  define 'handle error' do
    participant 'handle_error', :msg => 'on_error!'
  end
end

ruote.noisy = true
wfid = ruote.launch(pdef)
ruote.wait_for(wfid)

PartA and PartB are the same, except for the different Error. A few notes:

1. If you change self.class to "some string", it works. In this part, I'm not sure if it's some Ruby behavior I'm not familiar with, or some context related behavior that is caused by Ruote (or a totally different thing). I suspect a context issue because if you set "#{self.class}" then it works, so maybe self.class is being sent in a different context where it doesn't exist. I didn't use self.class when I saw the issue first, I called some different method.
2. If you change NameError to StandardError or RuntimeError, it works.
3. You can remove the :on_error attribute and it behaves the same, it was for me to check if maybe having an on_error handler changes the flow so that it works around this problem.

Does ruote handle different exceptions in a special way? Do I miss some fundamental Ruby behavior? (feeling kinda silly here :P)

Thanks,
Or

John Mettraux

unread,
Oct 27, 2013, 6:34:09 AM10/27/13
to openwfe...@googlegroups.com
Hello,

I'm still digesting your email, but I have a quick question: which Ruby
version on which platform?

Thanks in advance,

--
John Mettraux - http://lambda.io/jmettraux

Or Cohen

unread,
Oct 27, 2013, 6:42:49 AM10/27/13
to openwfe...@googlegroups.com
Ruby 1.9.3-p448 (using rvm) on Ubuntu 13.10

John Mettraux

unread,
Oct 27, 2013, 7:27:40 AM10/27/13
to openwfe...@googlegroups.com
Hello,

before deciding if I should fix that in ruote, I looked at it from irb (ruby
1.9.3p392 on Debian GNU/Linux 7).

Doing "raise NameError, String" results in a NameError that makes irb exit.

```
NameError: /opt/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/irb.rb:168:in `to_s':
can't convert Class into String (TypeError)
```

Doing "raise NameError, "String"" results in a "normal" NameError.

```
NameError: String
```

Looking at the documentation of raise:

http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-raise

Are you sure you want to use raise(class, class) where raise(class, string)
is expected?

(If that's a new thing in Ruby 1.9 or 2.0 please point me to the doc (that
made you use raise(class, class))).


Best regards,

--
John Mettraux - http://lambda.io/jmettrauX

Or Cohen

unread,
Oct 28, 2013, 5:37:16 AM10/28/13
to openwfe...@googlegroups.com
Hello,

Thank you for the quick response. You are right, the documentation states that this should be a string, and it does work when passing a string.

I'd still like to note that this is an inconsistent behavior in Ruby, and the fact that IRB crashes is even more weird (a REPL should never crash):

> StandardError.new("foo") # => <StandardError: foo>
> StandardError.new(String) # => <StandardError: String>
> NameError.new("foo") # => <NameError: foo>
> NameError.new(String) # => Exception: `to_s': can't convert Class into String (TypeError)

I've sent a patch (http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/43447) and it was accepted so I guess that solves it.
Since this is a language (probably even implementation specific) bug, there's no point in fixing anything in ruote. I'm still wondering where the exception went, though.

Thank you, again.
--
Or Cohen.

John Mettraux

unread,
Oct 28, 2013, 5:21:19 PM10/28/13
to openwfe...@googlegroups.com

On Mon, Oct 28, 2013 at 02:37:16AM -0700, Or Cohen wrote:
>
> Thank you for the quick response. You are right, the documentation states
> that this should be a string, and it does work when passing a string.
>
> I'd still like to note that this is an inconsistent behavior in Ruby, and
> the fact that IRB crashes is even more weird (a REPL should never crash):
>
> > StandardError.new("foo") # => <StandardError: foo>
> > StandardError.new(String) # => <StandardError: String>
> > NameError.new("foo") # => <NameError: foo>
> > NameError.new(String) # => Exception: `to_s': can't convert Class into
> String (TypeError)
>
> I've sent a patch (
> http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/43447)
> and it was accepted so I guess that solves it.

Hello Or,

thanks for making Ruby better.


> Since this is a language (probably even implementation specific) bug,
> there's no point in fixing anything in ruote. I'm still wondering where the
> exception went, though.

I've added ```Thread.abort_on_exception = true``` on top of your sample code
and saw this:

```
7 13:14.466 80 di * 20131028-2113-jogegita-namesoso 2384e 0_1 part_a wi:
[0_1!2384e...!, 1], part: [PartA, {}]
/home/jmettraux/w/ruote/lib/ruote/exp/ro_on_x.rb:43:in `to_s': can't convert
Class into String (TypeError)
from /home/jmettraux/w/ruote/lib/ruote/exp/ro_on_x.rb:43:in `message'
from /home/jmettraux/w/ruote/lib/ruote/exp/ro_on_x.rb:43:in `deflate'
from /home/jmettraux/w/ruote/lib/ruote/svc/error_handler.rb:167:in `deflate'
from /home/jmettraux/w/ruote/lib/ruote/svc/error_handler.rb:152:in `rescue in handle'
from /home/jmettraux/w/ruote/lib/ruote/svc/error_handler.rb:110:in `handle'
from /home/jmettraux/w/ruote/lib/ruote/svc/error_handler.rb:65:in `msg_handle'
from /home/jmettraux/w/ruote/lib/ruote/svc/dispatch_pool.rb:98:in `rescue in do_dispatch'
from /home/jmettraux/w/ruote/lib/ruote/svc/dispatch_pool.rb:95:in `do_dispatch'
from /home/jmettraux/w/ruote/lib/ruote/svc/dispatch_pool.rb:115:in `block in do_threaded_dispatch'
```

The "can't convert Class into String" happens in the rescue handler, and
since it happens in the dispatch thread it is silently happening (and the
flow stalls).

I need to make sure the exception gets reported: https://github.com/jmettraux/ruote/issues/90


Thanks a lot!

--
John Mettraux - http://lambda.io/jmettraux

John Mettraux

unread,
Oct 28, 2013, 6:07:22 PM10/28/13
to openwferu-users
Made sure the error got to the fallback error handler.

Thanks again,

John

Or Cohen

unread,
Oct 29, 2013, 9:51:25 AM10/29/13
to openwfe...@googlegroups.com
Awesome! Thank you very much for quickly handling this and providing a solution :)
Reply all
Reply to author
Forward
0 new messages