如何在Ruby中使用信号阻塞

前端之家收集整理的这篇文章主要介绍了如何在Ruby中使用信号阻塞前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何阻止 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

猜你在找的Ruby相关文章