如何在EventMachine实现中捕获exception?
我对这个post有类似的问题,我尝试了给定的解决方案,但无济于事。
我的项目是一个Ruby bot,它使用Blather库连接到Jabber服务器。 问题是,当服务器出现问题并且Blather生成exception时,整个程序退出,我没有机会捕获exception。
这是一些显示问题的简单代码。 在localhost上没有运行Jabber服务器,因此Blather客户端抛出exception。 我的印象是EM.error_handler {}能够拦截它,但我从未看到**** ERROR
消息,程序就停止了。 🙁
#!/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
我认为问题是Blather也使用EventMachine并且可能正在调用EM.stop,这会导致外部EM实例停止。
exception和异步编程不是朋友,因此正确处理它们可能很棘手。 在同步模型中,可以通过对可能产生exception的代码块使用rescue
来捕获exception,但是一旦创建了回调方法,该块就需要自己的exception处理,因为它将在该上下文之外运行。
希望error_handler
能捕获您的exception,但如果您有其他涉及的线程可能无法捕获它们。
您可以始终monkeypatch EventMachine.stop_event_loop
和EventMachine.stop_server
来查看是否正在调用该方法。
error_handler捕获在执行事件循环中触发的回调期间发生的exception。 在上面的代码崩溃的时候你不会启动循环。 (我假设Blather :: Stream.start而不是上面的Blather :: Stream :: Client.start)。
您可以尝试执行EM.next_tick {Blather :: Stream.start(…)},这会强制它在reactor循环期间执行。
但是,一般情况下,您不希望在error_handler触发后继续。 它基本上是最后一道防线,可以清理任何状态并退出(并打印堆栈跟踪,以便了解应用程序崩溃的原因)。 当它触发时你不知道你的应用程序的当前状态是什么,你不能真正相信状态是正确的或一致的。
理论上,您可以将Blather调用包装在开始/救援中:
begin Blather::Stream.start(...) rescue Exception => e puts e end
哪个应该为你做,你可以坚持一些重试逻辑。
- 使用EventMachine时为什么会有这么多“TIME_WAIT”连接?
- Eventmachine start_tcp_server没有接受者 – 端口正在使用或需要root权限(RuntimeError)
- Ruby IMAP IDLE并发 – 如何解决?
- 简单使用EM :: Synchrony#sync导致’根光纤’FiberError – 我的错?
- 如何从Rails控制器推送到Faye Server?
- 如何使用em_mysql2解决’连接仍在等待结果’错误
- 使用sinatra流API的异步请求
- 最好使用EM.next_tick或EM.defer与Eventmachine进行长时间运行计算?
- 使用em-http-request无法获得性能