终止时终止所有线程

时间:2014-12-24 23:09:33

标签: ruby multithreading

我试图在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 }

上面的代码确实很好地完成了它的工作 - sinatra应用程序在4567端口下启动,do something heavy任务每10秒启动一次。但是,我无法杀死那个剧本。

我用ruby app.rb运行它但是用ctrl + c查杀它是行不通的。它只杀死sinatra线程但第二个仍在运行,为了停止脚本,我需要关闭终端窗口。

我试图杀死SIGNINT上的所有主题,但它也没有按预期工作

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

你能帮我解决这个问题吗?提前谢谢。

2 个答案:

答案 0 :(得分:2)

要捕获ctrl-c,请将“SIGINT”更改为“INT”。

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

配置Sinatra以跳过捕获陷阱:

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

参考:Ruby Signal module

列出可用的Ruby信号:Signal.list.keys

参考:Sinatra Intro

(当我运行你的代码并捕获INT时,我确实得到一个Sinatra套接字警告“已经在使用中”。我认为这对你的目的来说很好,或者你可以通过Sinatra优雅关闭来解决这个问题。见{{3 }})

答案 1 :(得分:0)

晚了聚会,但是Trap有一个很大的缺点-网络服务器会覆盖它。例如,彪马设置了几个陷阱,这些陷阱基本上使您永远不会被召唤。

最好的解决方法是使用at_exit,它可以多次定义,并且Ruby确保所有块都被调用。我还没有测试过它是否适合您的情况。