Jruby Rake任务 - 捕获INT信号时Thread.current更改

时间:2013-11-20 19:01:32

标签: jruby rake-task signal-handling

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中的相同代码工作精细。 Thread.current仍然相同。

问题:

  1. 在JRuby中,为什么Thread.current在信号捕获期间有所不同?
  2. 是一个单独的生成线程只是为了处理信号?
  3. PLUS,在信号处理程序中(再次),当我尝试访问已经创建的Redis连接时,它无限期地停止,什么都不返回! [仅在JRuby中发生,不确定是否与信号处理有关。]

1 个答案:

答案 0 :(得分:0)

我认为没有任何保证你的信号处理程序会发生什么线程。即使在像C with pthreads这样的其他语言中,这种事情也很复杂。

我也怀疑Ruby 强制要求一个特定的线程会收到你的信号,只是碰巧“主”线程就是那个。这可能在未来发生变化。

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