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.



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

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.



10
11
12
# File 'lib/overcommit/interrupt_handler.rb', line 10

def isolate_signals
  @isolate_signals
end

#reenable_on_interruptObject

Returns the value of attribute reenable_on_interrupt.



10
11
12
# File 'lib/overcommit/interrupt_handler.rb', line 10

def reenable_on_interrupt
  @reenable_on_interrupt
end

#signal_receivedObject

Returns the value of attribute signal_received.



10
11
12
# File 'lib/overcommit/interrupt_handler.rb', line 10

def signal_received
  @signal_received
end

Class Method Details

.disable!Object

Disable interrupt isolation.



71
72
73
# File 'lib/overcommit/interrupt_handler.rb', line 71

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


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

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.



76
77
78
# File 'lib/overcommit/interrupt_handler.rb', line 76

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



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

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