How to use signal blocking in Ruby How to use signal blocking in Ruby ruby ruby

How to use signal blocking in Ruby


I think you're looking for the 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.

So you should be able to say this:

trap('INT', 'IGNORE')something_that_must_not_be_interruptedtrap('INT', 'DEFAULT')

UPDATE: From the comments, it looks like you only want to temporarily ignore the signal. The easiest way to do that with what you already have is to add a flag that your signal handler can see, then remember the signal when it comes in and we're currently ignoring the signal, and when we're not ignoring things anymore you just empty the signal queue by sending them to yourself. If wrap this logic up in a class, you'll have something fairly friendly:

## 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) }  endend

The real functional code was the easiest way to explain the technique (and I had to write it anyway to make sure the technique would work) so there you go. And thanks for the review of signal handling in Ruby :) Then you could so things like this:

sigint = SignalHandler.new('INT')loop do  this_could_be_interrupted  sigint.dont_interupt { something_that_must_not_be_interrupted }  this_could_be_interrupted_tooend


Ruby returns the last handler associated with the signal, so you can use:

def bypass_signal(name)  old_handler = trap("INT", 'IGNORE')  yield  trap("INT", old_handler)endbypass_signal "INT" { method_which_shouldnt_be_interrupted }