2014-12-24 26 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