我试图使用 Kernel#trap 捕获信号,并在该上下文中运行数据库请求,但出现上述错误。以前有人遇到过吗?有什么办法解决吗?
示例代码:
trap('HUP') do
$db[:db_name].update({_id: 123}, {:$set => {a: 1}})
end
loop { sleep 1 }
会报这个错误:
/usr/local/lib/ruby/gems/2.1.0/gems/mongo-1.11.1/lib/mongo/connection/pool.rb:266:in `synchronize': can't be called from trap context (ThreadError)
当脚本收到 HUP 信号时,可以通过运行发送kill -HUP {pid}
。 $db 必须是 MongoDB 对象。
Ruby 不允许在陷阱上下文中进行互斥同步,大概是因为它可能导致死锁(即,您处于同步上下文中,然后向进程发送信号并尝试重新同步,从而导致死锁)。您可以通过以下方式简单地重现这一点:
# trap.rb
require 'thread'
mutex = Mutex.new
trap('HUP') { mutex.synchronize {} }
gets
# pkill -HUP -f trap.rb
trap.rb:3:in `synchronize': can't be called from trap context (ThreadError)
from trap.rb:3:in `block in <main>'
from trap.rb:4:in `call'
from trap.rb:4:in `gets'
from trap.rb:4:in `gets'
from trap.rb:4:in `<main>'
为了解决这个问题,您的信号处理程序可能应该将作业排队以由另一个线程处理,或者您可以生成一个新线程并在其中执行您的工作:
# trap.rb
require 'thread'
mutex = Mutex.new
trap('HUP') do
Thread.new { mutex.synchronize { puts "hi!" } }
end
gets
# pkill -HUP -f trap.rb
hi!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)