2014-12-24 210 views
3

我試圖創建一個可以從命令行啓動的ruby應用程序,它有兩件事:運行一個連續的作業(loopsleep,它運行一些操作[遠程提要解析])與一個線程和sinatra在第二個線程中。我的代碼(簡體)看起來像這樣:終止終止所有線程

require 'sinatra' 

class MyApp < Sinatra::Base 
    get '/' do 
    "Hello!" 
    end 
end 

threads = [] 

threads << Thread.new do 
    loop do 
    # do something heavy 
    sleep 10 
    end 
end 

threads << Thread.new do 
    MyApp.run! 
end 

threads.each { |t| t.join } 

上面的代碼實際上做了它的工作非常好 - 西納特拉的應用程序是在4567端口開始可用和do something heavy任務beeing解僱每次10秒。但是,我無法殺死那個腳本。

我正在運行它與ruby app.rb但用ctrl + c殺死它不起作用。它殺死了sinatra線程,但第二個仍在運行,爲了停止腳本,我需要關閉終端窗口。

我試圖殺死SIGNINT所有的線程,但它如預期

trap "SIGINT" do 
    puts "Exiting" 
    threads.each { |t| Thread.kill t } 
    exit 130 
end 

你能不能幫我這也沒有工作?提前致謝。

+0

您是否看到「puts」的輸出Exiting「'? – Humza

+0

不幸的是,我不 – mbajur

+1

這顯然意味着你的'陷阱'不工作。作爲一個附註,我建議通過'thread.exit'而不是'Thread.kill(thread)'來退出線程 - 它更簡潔。 – Humza

回答

2

要捕獲ctrl-c,請將「SIGINT」更改爲「INT」。

trap("INT") { 
    puts "trapping" 
    threads.each{|t| 
    puts "killing" 
    Thread.kill t 
    } 
} 

配置西納特拉跳過捕陷阱:

class MyApp < Sinatra::Base 
    configure do 
    set :traps, false 
    end 
    ... 

參考:紅寶石Signal module

要列出可用紅寶石信號:Signal.list.keys

參考:Sinatra Intro

(當我運行你r代碼和陷阱INT,我得到一個Sinatra插座警告「已經在使用」。我認爲這對你的目的很好,或者你可以通過Sinatra的優雅關機來解決這個問題。請參閱Sinatra - terminate server from request

+0

將SIGNINT更改爲INT之後,按ctrl + c後我所得到的是'^ C == Sinatra已經結束了他的設置(衆人鼓掌)'而且我仍然無法終止那個混蛋 – mbajur

+0

@mbajur it似乎sinatra是捕獲的信號之前,它到達你的信號,在這裏https://github.com/sinatra/sinatra/blob/4e92d604be5269b1d6527a6093f112d10b5b9d7f/lib/sinatra/base.rb#L1523-L1528,所以你可能想'設置:陷阱,錯誤'在'configure'塊中 – bjhaid

+0

我爲你添加了Sinatra代碼 - 它與@bjhaid所暗示的代碼相同,只是複數的「陷阱」。 – joelparkerhenderson