我的猜测是,要么是某些东西阻碍了 EventMachine 反应器循环,阻止它退出,要么是某些东西在捕获 SIGINT。
作为前者的一个简单示例,将其放入config.ru
并运行thin -p 4567 start
:
require 'thin'
require 'sinatra'
require 'eventmachine'
get '/' do
"hello world"
end
run Sinatra::Application
EventMachine.schedule do
trap("INT") do
puts "Caught SIGINT"
EventMachine.stop # this is useless
# exit # this stops the EventMachine
end
i = 0
while i < 10
puts "EM Running"
i += 1
sleep 1
end
end
如果不捕获 SIGINT,您将获得与捕获它并调用 EM.stop 时相同的行为。EM.stop (至少在纯 ruby 版本中,您可以使用它运行EVENTMACHINE_LIBRARY="pure_ruby" thin start
)设置一个已请求停止的标志,该标志在反应器循环内被拾取。如果反应器回路卡在台阶上(如上述情况),则它不会退出。
所以有几个选择:
使用上述捕获 SIGINT 并强制退出的解决方法。这可能会使连接处于不干净的状态,但他们不会无缘无故地称之为快速和肮脏;)
您可以将阻塞代码放在 Thread 或 Fiber 中,这将允许反应器继续运行。
在代码中查找长时间运行的任务或循环,并将它们转换为 EventMachine 感知的。em-http-request 是一个很好的外部 http 请求库,em-synchrony 还有其他几个协议(用于数据库连接、tcp 连接池等)。在上面的示例中,这很简单:EventMachine.add_periodic_timer(1) { puts "EM Running" }
在您的实际代码中,这可能更难追踪,但请寻找您产生线程并加入它们的任何地方,或大型循环。当您尝试退出时,分析工具可以帮助显示正在运行的代码,最后您可以尝试禁用系统和库的各个部分以找出罪魁祸首。