如何阻止
Ruby中的某些信号? (即,sigprocmask,如下所述:
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_21.html#SEC371)
这是我的示例代码
pid = fork do trap('INT') do puts "Graceful shutdown..." puts "goodbye" exit 0 end loop do this_could_be_interrupted something_that_must_not_be_interrupted this_could_be_interrupted_too end end sleep 5 Process.kill('INT',pid)
我可以在ruby块或某些东西中包装something_that_must_not_be_interrupted以确保在该方法运行时SIGINT不会被处理吗?
我想,如果我能做这样的事情,理想的是:
Process.block_signal('INT') do something_that_must_not_be_interrupted end
更新:我正在做这样的事情:
trap('INT') do @interrupted = true end loop do exit 0 if @interrupted something_that_must_not_be_interrupted end
解决方法
我想你正在寻找
non-block form of
trap
:
Signal.trap( signal,command ) → obj
[…]
If the command is the string"IGNORE"
or"SIG_IGN"
,the signal will be ignored. If the command is"DEFAULT"
or"SIG_DFL"
,the Ruby‘s default handler will be invoked.
所以你应该可以这样说:
trap('INT','IGNORE') something_that_must_not_be_interrupted trap('INT','DEFAULT')
更新:从评论中,您只需要暂时忽略该信号.使用您已经拥有的最简单的方法是添加一个标志,您的信号处理程序可以看到,然后记住信号,当它进来,我们目前忽略信号,当我们不再忽视的东西了只需将信号队列发送给自己即可.如果把这个逻辑包装在一个类中,你会有一些相当友好的东西:
# # Threading and race condition issues are left as an exercise,# this is just meant as an illustration. Handling multiple signals # at once is also left as an exercise. # class SignalHandler def initialize(signal) @interuptable = true @enqueued = [ ] trap(signal) do if(@interuptable) puts "Graceful shutdown..." puts "goodbye" exit 0 else @enqueued.push(signal) end end end # If this is called with a block then the block will be run with # the signal temporarily ignored. Without the block,we'll just set # the flag and the caller can call `allow_interuptions` themselves. def dont_interupt @interuptable = false @enqueued = [ ] if(block_given?) yield allow_interuptions end end def allow_interuptions @interuptable = true # Send the temporarily ignored signals to ourself # see http://www.ruby-doc.org/core/classes/Process.html#M001286 @enqueued.each { |signal| Process.kill(signal,0) } end end
真正的功能代码是解释技术的最简单的方法(我必须写它来确保技术可以工作),所以你去.感谢Ruby的信号处理审查:)那么你可以这样做:
sigint = SignalHandler.new('INT') loop do this_could_be_interrupted sigint.dont_interupt { something_that_must_not_be_interrupted } this_could_be_interrupted_too end