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