如何在 EventMachine 实现中捕获异常?
Posted
技术标签:
【中文标题】如何在 EventMachine 实现中捕获异常?【英文标题】:How do you catch exceptions in an EventMachine implementation? 【发布时间】:2011-12-07 13:49:15 【问题描述】:我遇到了与this other post 类似的问题,我尝试了给定的解决方案,但无济于事。
我的项目是一个 Ruby 机器人,它使用 Blather 库连接到 Jabber 服务器。问题是,当服务器出现问题并且 Blather 生成异常时,整个程序都会退出,而我没有机会捕捉到异常。
这里有一些显示问题的简单代码。本地主机上没有运行 Jabber 服务器,因此 Blather 客户端会引发异常。我的印象是 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 实例停止。
【问题讨论】:
【参考方案1】:异常和异步编程不是朋友,因此很难正确处理它们。在同步模型中,可以通过在可能产生异常的代码块上使用 rescue
来捕获异常,但是一旦创建了回调方法,该代码块就需要自己的异常处理,因为它将在该上下文之外运行。
希望error_handler
能够捕获您的异常,但如果您涉及其他线程可能无法捕获它们。
您总是可以对EventMachine.stop_event_loop
和EventMachine.stop_server
进行monkeypatch 以查看是否是被调用的方法。
【讨论】:
嗯...这不是最佳解决方案。error_handler
应该 捕捉到这些东西,但不是出于某种原因。我会给猴子补丁选项一试,看看我是否可以通过这种方式“解决”我的问题。 ://
猴子补丁只是为了查看这些方法是否被调用,因为之后不再需要它们。【参考方案2】:
error_handler 捕获在事件循环中触发的回调执行期间发生的异常。您不会在上述代码崩溃时开始循环。 (我假设是 Blather::Stream.start 而不是上面的 Blather::Stream::Client.start)。
您可以尝试执行 EM.next_tick Blather::Stream.start(...) ,这将强制它在反应器循环期间执行。
但是,一般来说,您不希望在 error_handler 触发后继续。它基本上是您清理任何状态并退出的最后一道防线(并打印堆栈跟踪,以便您知道应用程序崩溃的原因)。当它触发时,您不知道应用程序的当前状态是什么,并且您无法真正相信该状态是正确的或一致的。
理论上,您可以将 Blather 调用包装在 begin/rescue 中:
begin
Blather::Stream.start(...)
rescue Exception => e
puts e
end
这应该对你有用,然后你可以坚持一些重试逻辑。
【讨论】:
【参考方案3】:您可以通过这种方式附加error_handler
:
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
【讨论】:
以上是关于如何在 EventMachine 实现中捕获异常?的主要内容,如果未能解决你的问题,请参考以下文章
ajax请求后台代码,如何实现后台抛出异常在前台捕获异常:如后台抛出throw exception("该帖子已被删除")