MongoDB Ruby驱动程序 - “synchronize'”无法从陷阱上下文中调用

时间:2015-01-20 08:20:30

标签: ruby mongodb

我正在尝试使用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对象。

1 个答案:

答案 0 :(得分:2)

Ruby不允许在陷阱上下文中进行Mutex同步,大概是因为它可能导致死锁(即,您处于同步上下文中,然后向进程发送信号并尝试重新同步,在此情况下您将死锁) 。您可以通过以下方式轻松复制:

# 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!