Sinatra/Thin运行时无法使用Ctrl-C停止

3
我正在创建一个应用程序,其中Sinatra运行在EventMachine中,当我运行最基本的测试应用程序时,我无法使用Ctrl-C结束服务器,我必须使用-9或-usr2进行杀死。
我无法弄清楚为什么Sinatra报告已停止但继续提供请求,或者为什么我无法使用Ctrl-C停止服务器。
Thin 1.6.1与Sinatra 1.4.4已停止消息但继续。
== Sinatra/1.4.4 has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.6.1 codename Death Proof)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
Stopping ...
== Sinatra has ended his set (crowd applauds)
Ping!
^CPing!
Stopping ...
Ping!
^CStopping ...

这是我用来生成输出的基本测试应用程序。
# Run with 'ruby test.rb'
require 'eventmachine'
require 'sinatra/base'
require 'thin'

class NeverStops < Sinatra::Base
  settings.logging = true

  configure do
    set :threaded, true
  end

  get '/foobar' do
    'Foobar'
  end
end

EM.run do

  # Does nothing
  #trap(:INT) { EM::stop(); exit }
  #trap(:TERM) { EM::stop(); exit }
  #trap(:KILL) { EM::stop(); exit }

  EventMachine.add_periodic_timer 2 do
    puts 'Ping!'
  end

  NeverStops.run!
end

降级Thin或Sinatra的结果不同。

Thin 1.6.1与Sinatra 1.4.3无停止消息但仍无法关闭(确实是“死亡证明”)

== Sinatra/1.4.3 has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.6.1 codename Death Proof)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
Ping!
^CPing!
Stopping ...
Ping!

Thin 1.5.1与Sinatra 1.4.4一起使用时会突然停止运行

== Sinatra/1.4.4 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop
>> Stopping ...
== Sinatra has ended his set (crowd applauds)

Thin 1.5.1 和 Sinatra 1.4.3 可以正常工作

== Sinatra/1.4.3 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop
Ping!
Ping!
Ping!
^C>> Stopping ...

== Sinatra has ended his set (crowd applauds)

我已经将我的gems更新到最新版本,尝试降低EventMachine和Rack等各种gem的版本以查看结果,但没有任何有用的不同。

版本

  • OSX 10.8.5和Ubuntu 12.04.1
  • Ruby 2.0.0p247和1.9.3p194
  • eventmachine 1.0.3
  • rack 1.5.2
  • sinatra 1.4.4
  • thin 1.6.1
  • tilt 1.4.1

看起来是一个双重问题 http://stackoverflow.com/questions/19299932/ctrlc-not-killing-sinatra-emwebsocket-servers - bbozo
2个回答

2
这个问题只出现在较新版本的Thin中(注意v1.5.1没有这个问题)。这个问题是在1.6中引入的,类似的问题在这里有记录。
涉及到的代码遵循上游问题中提到的相同模式。
简要概述一下问题:Thin会停止服务器,但不会停止反应器循环(因为它不“拥有”反应器)。可以让Thin拥有它的反应器循环,这样就可以得到期望的行为(如1.5.1所示)。为此,必须在不带封闭EM#run { }的情况下启动Thin,这将允许Thin启动(然后关闭)反应器循环。
在这种情况下,可以将周期性的“ping”想象成一个与Thin共享反应器循环的独立应用程序。它们都不能声称拥有反应器循环。当Thin没有启动反应器时,停止所有其他应用程序并退出反应器是错误的。然后用户需要处理信号并根据需要终止各个应用程序,最后停止反应器循环(导致进程退出)。
希望这个解释能够帮助你!

1
我也遇到了这个问题,但我并不真正理解解决方案。您如何确切地设置Thin拥有反应器循环? - Terence Chow
在原始问题中提到的代码片段中,您可以消除所有处理 EM.run 循环的代码,而是直接调用 YouApp.run! - Akshay M
1
如果您正在另一个EM反应器中运行Thin,并且需要该反应器响应INT,则将选项signals: false传递给Thin,以防止其捕获信号并不杀死反应器。 - Michael Papile
@MichaelPapile,如何进行此设置? - Julian Veling

-1

Thin 正在利用 EM,您应该像使用 Webrick 一样运行您的应用程序,而不是使用 EM。例如 config.ru:

require 'bundler'
Bundle.require

class UseToStop < Sinatra::Base
  get '/foobar' { body "Foobar" }
end

run UseToStop

你确定需要这个选项吗?这会使事情变得更加复杂,而这是你最不需要的。

set :threaded, true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接