5

bundle exec thin start -p 3111给出以下输出:

使用机架适配器瘦 Web 服务器(v1.2.11 代号 Bat-Shit Crazy)最大连接数设置为 1024 监听 0.0.0.0:3111,CTRL+C 停止 ^C

Ctrl-C 不执行任何操作(SIGINT)。也不会杀死(SIGTERM)。

我发现了一些关于这种行为的参考,但没有解决方案。问题似乎出在 eventmachine(与最新的 Thin 捆绑)、ruby 1.9.2-r290 或 linux 内核(Ubuntu 10.4 LTS、2.6.38.3-linode32)中。

它发生在我的项目中,但没有发生在全新的 Rails 项目中。

参考:

4

1 回答 1

5

我的猜测是,要么是某些东西阻碍了 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)设置一个已请求停止的标志,该标志在反应器循环内被拾取。如果反应器回路卡在台阶上(如上述情况),则它不会退出。

所以有几个选择:

  1. 使用上述捕获 SIGINT 并强制退出的解决方法。这可能会使连接处于不干净的状态,但他们不会无缘无故地称之为快速和肮脏;)

  2. 您可以将阻塞代码放在 Thread 或 Fiber 中,这将允许反应器继续运行。

  3. 在代码中查找长时间运行的任务或循环,并将它们转换为 EventMachine 感知的。em-http-request 是一个很好的外部 http 请求库,em-synchrony 还有其他几个协议(用于数据库连接、tcp 连接池等)。在上面的示例中,这很简单:EventMachine.add_periodic_timer(1) { puts "EM Running" }

在您的实际代码中,这可能更难追踪,但请寻找您产生线程并加入它们的任何地方,或大型循环。当您尝试退出时,分析工具可以帮助显示正在运行的代码,最后您可以尝试禁用系统和库的各个部分以找出罪魁祸首。

于 2011-07-20T08:49:40.610 回答