Jruby Rake任务-捕获INT信号时线程当前更改



jruby-1.7.6上运行的rake任务中,我根据需要生成许多线程,并存储每个生成的线程:

puts Thread.current # => #<Thread:0x1e95aeb7>
Thread.current[:spawned_threads] = {}
# New thread spawned for every new request and stored and
# Thread.current obviously remains the same:
puts Thread.current # => #<Thread:0x1e95aeb7>
thread_object = Thread.new {
  # code in infinite loop
}
Thread.current[:spawned_threads]["thread_#{counter}"] = thread_object

当我退出rake任务时,我会终止所有派生的线程。我使用信号处理程序:

trap('INT')  { 
  terminate_threads
  exit!
}
def terminate_threads
  puts Thread.current                   # => #<Thread:0x7604790c> A different thread!
  puts Thread.current[:spawned_threads] # => nil
  Thread.current[:spawned_threads].each do |key, thread| # Error!!!
    thread.terminate             
  end
end

解决方法:Thread.list.last[:spawned_threads]拥有我所有的派生线程。

但是等一下,

RUBY 1.9.3中的相同代码工作正常。线程电流保持不变

问题:

  1. 在JRuby中,为什么Thread.current在信号捕获过程中不同
  2. 一个单独的正在生成的线程只是为了处理信号吗

另外,在信号处理程序中(再次),当我试图访问已经创建的Redis连接时,它会无限期地暂停,什么也不返回![仅在JRuby中发生,不确定是否与信号处理有关。]

我不认为有任何保证你的信号处理程序会在哪个线程中发生。即使在其他语言中,比如C和pthreads,这种事情也很复杂。

我还怀疑Ruby命令一个特定的线程是否会接收到你的信号,只是碰巧"主"线程会接收到信号。这种情况在未来可能会改变。

您应该重组您的代码,以便有一个众所周知的地方可以从任何线程向其发送消息。这可能采取全局变量的形式。然后,您将需要为该对象的方法提供适当的多线程保护,因为您永远不知道哪个线程将在何时调用方法。

最新更新