Ответ 1
Я думаю, что вы ищете неблокированную форму trap
:
Signal.trap( signal, command ) → obj
[...]
Если команда представляет собой строку"IGNORE"
или"SIG_IGN"
, сигнал будет проигнорирован. Если команда"DEFAULT"
или"SIG_DFL"
, вызывается обработчик по умолчанию Ruby.
Итак, вы должны это сказать:
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