How do you get exceptions in the implementation of EventMachine?

I have a similar problem with this other post and I tried these solutions, but to no avail.

My project is a Ruby robot that uses the Blather library to connect to a Jabber server. The problem is that when there is a problem with the server, and Blather throws an exception, the whole program terminates, and I have no way to catch the exception.

Here is a simple code that shows the problem. The Jabber server is not running on the local host, so the Blather client throws an exception. I got the impression that EM.error_handler {} would be able to intercept it, but I never see the **** ERROR message and the program just stops. :(

 #!/usr/bin/env ruby require 'rubygems' require 'blather/client/client' EM.run do EM.error_handler { puts " **** ERROR " } Blather::Stream::Client.start( Class.new { }.new, ' echo@127.0.0.1 ', 'echo') end 

I think the problem is that Blather also uses EventMachine and possibly calls EM.stop, which causes the external EM instance to stop.

+6
source share
3 answers

Exceptions and asynchronous programming are not friends, so they can be difficult to handle correctly. In a synchronous model, an exception can be caught using rescue in a code block that can throw exceptions, but once you create a callback method, this block needs its own exception handling because it will work outside of this context.

We hope that error_handler will catch your exception, but if you have other threads that may not be able to catch them.

You can always monkeypatch EventMachine.stop_event_loop and EventMachine.stop_server to find out if this method is called.

+5
source

Error_handler catches exceptions that occur during callbacks that are raised in the event loop. You did not start the loop at the point where the code above is. (I assume Blatter :: Stream.start instead of Blatter :: Stream :: Client.start above).

You can try executing EM.next_tick {Blather :: Stream.start (...)}, which will force it to execute during the reactor cycle.

But, in general, you do not want to continue working after running error_handler. This is basically the last protection line for you to clear any state and exit (and print a stack trace so you know why the application crashed). When it fires, you have no idea what the current state of your application is in, and you cannot really trust the correct or consistent state.

In theory, you can simply wrap Blather's call at the start / save:

 begin Blather::Stream.start(...) rescue Exception => e puts e end 

What should do the trick for you, you could stick to the logic of repetition.

+2
source

You can attach error_handler as follows:

 require 'eventmachine' EM.run do # your stuff end # Outside 'EM.run' EM.error_handler do |e| # Then you can do something like these: puts e.message puts e.inspect puts e.backtrace.join("\n") end 
+1
source

Source: https://habr.com/ru/post/903293/


All Articles