gpt4 book ai didi

ruby - 如何在 Ruby 中使用信号阻塞

转载 作者:数据小太阳 更新时间:2023-10-29 06:39:12 24 4
gpt4 key购买 nike

如何在 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)

我能否将 something_that_must_not_be_interrupted 包装在 ruby​​ block 或其他东西中以确保在该方法运行时不会处理 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://ruby-doc.org/core/Process.html#method-c-kill
@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 - 如何在 Ruby 中使用信号阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6354043/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com