Class: InterruptHandler

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/overcommit/interrupt_handler.rb

Overview

Provides a handler for interrupt signals (SIGINT), allowing the application to finish what it’s currently working on.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeInterruptHandler

Initialize safe interrupt signal handling.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/overcommit/interrupt_handler.rb', line 11

def initialize
  self.isolate_signals = false
  self.signal_received = false
  self.reenable_on_interrupt = false

  Signal.trap('INT') do
    if isolate_signals
      self.signal_received = true
    else
      if reenable_on_interrupt
        self.reenable_on_interrupt = false
        self.isolate_signals = true
      end

      raise Interrupt # Allow interrupt to propagate to code
    end
  end
end

Instance Attribute Details

#isolate_signalsObject

Returns the value of attribute isolate_signals.



8
9
10
# File 'lib/overcommit/interrupt_handler.rb', line 8

def isolate_signals
  @isolate_signals
end

#reenable_on_interruptObject

Returns the value of attribute reenable_on_interrupt.



8
9
10
# File 'lib/overcommit/interrupt_handler.rb', line 8

def reenable_on_interrupt
  @reenable_on_interrupt
end

#signal_receivedObject

Returns the value of attribute signal_received.



8
9
10
# File 'lib/overcommit/interrupt_handler.rb', line 8

def signal_received
  @signal_received
end

Class Method Details

.disable!Object

Disable interrupt isolation.



69
70
71
# File 'lib/overcommit/interrupt_handler.rb', line 69

def disable!
  instance.isolate_signals = false
end

.disable_until_finished_or_interruptedObject

Provide a way to allow a single Ctrl-C interrupt to happen and atomically re-enable interrupt protections once that interrupt is propagated.

This prevents a race condition where code like the following:

begin
  InterruptHandler.disable!
  ... do stuff ...
rescue Interrupt
  ... handle it ...
ensure
  InterruptHandler.enable!
end

…could have the enable! call to the interrupt handler not called in the event another interrupt was received in between the interrupt being handled and the ensure block being entered.

Thus you should always write:

begin
  InterruptHandler.disable_until_finished_or_interrupted do
    ... do stuff ...
  end
rescue Interrupt
  ... handle it ...
rescue
  ... handle any other exceptions ...
end


60
61
62
63
64
65
66
# File 'lib/overcommit/interrupt_handler.rb', line 60

def disable_until_finished_or_interrupted
  instance.reenable_on_interrupt = true
  instance.isolate_signals = false
  yield
ensure
  instance.isolate_signals = true
end

.enable!Object

Enable interrupt isolation.



74
75
76
# File 'lib/overcommit/interrupt_handler.rb', line 74

def enable!
  instance.isolate_signals = true
end

.isolate_from_interrupts { ... } ⇒ Object

Enable interrupt isolation while executing the provided block.

Yields:

  • block to execute with interrupt isolation



81
82
83
84
85
86
87
# File 'lib/overcommit/interrupt_handler.rb', line 81

def isolate_from_interrupts
  instance.signal_received = false
  instance.isolate_signals = true
  result = yield
  instance.isolate_signals = false
  result
end