私の推測では、何かが 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
) は、reactor ループ内で取得される停止が要求されたことを示すフラグを設定します。リアクター ループがステップで動かなくなった場合 (上記の場合のように)、ループは終了しません。
したがって、いくつかのオプションがあります:
SIGINT をトラップして終了を強制する上記の回避策を使用してください。これにより、接続が汚れた状態のままになる可能性がありますが、彼らはそれを無駄にクイック&ダーティとは呼びません;)
ブロック コードを Thread または Fibre 内に配置すると、reactor を実行し続けることができます。
コード内で実行時間の長いタスクまたはループを探し、これらを EventMachine 対応に変換します。em-http-request は外部 http リクエスト用の優れたライブラリであり、em-synchrony には他にもいくつかのプロトコル (データベース接続、tcp 接続プールなど) があります。上記の例では、これは簡単です。EventMachine.add_periodic_timer(1) { puts "EM Running" }
実際のコードでは、これを追跡するのは難しいかもしれませんが、スレッドを生成してそれらに参加する場所、または大きなループを探します。プロファイリング ツールは、終了しようとしたときに実行中のコードを表示するのに役立ちます。最後に、システムとライブラリのさまざまな部分を無効にして、原因がどこにあるかを突き止めることができます。