einhorn 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -147,25 +147,25 @@ module Einhorn::Command
147
147
 
148
148
  ## Signals
149
149
  def self.install_handlers
150
- Signal.trap("INT") do
150
+ trap_async("INT") do
151
151
  Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers)
152
152
  Einhorn::Command.stop_respawning
153
153
  end
154
- Signal.trap("TERM") do
154
+ trap_async("TERM") do
155
155
  Einhorn::Command.signal_all("TERM", Einhorn::WorkerPool.workers)
156
156
  Einhorn::Command.stop_respawning
157
157
  end
158
158
  # Note that quit is a bit different, in that it will actually
159
159
  # make Einhorn quit without waiting for children to exit.
160
- Signal.trap("QUIT") do
160
+ trap_async("QUIT") do
161
161
  Einhorn::Command.signal_all("QUIT", Einhorn::WorkerPool.workers)
162
162
  Einhorn::Command.stop_respawning
163
163
  exit(1)
164
164
  end
165
- Signal.trap("HUP") {Einhorn::Command.reload}
166
- Signal.trap("ALRM") {Einhorn::Command.full_upgrade}
167
- Signal.trap("CHLD") {Einhorn::Event.break_loop}
168
- Signal.trap("USR2") do
165
+ trap_async("HUP") {Einhorn::Command.reload}
166
+ trap_async("ALRM") {Einhorn::Command.full_upgrade}
167
+ trap_async("CHLD") {}
168
+ trap_async("USR2") do
169
169
  Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers)
170
170
  Einhorn::Command.stop_respawning
171
171
  end
@@ -177,6 +177,16 @@ module Einhorn::Command
177
177
  end
178
178
  end
179
179
 
180
+ def self.trap_async(signal, &blk)
181
+ Signal.trap(signal) do
182
+ # We try to do as little work in the signal handler as
183
+ # possible. This avoids potential races between e.g. iteration
184
+ # and mutation.
185
+ Einhorn::Event.break_loop
186
+ Einhorn::Event.register_signal_action(&blk)
187
+ end
188
+ end
189
+
180
190
  def self.remove_handlers
181
191
  %w{INT TERM QUIT HUP ALRM CHLD USR2}.each do |signal|
182
192
  Signal.trap(signal, "DEFAULT")
data/lib/einhorn/event.rb CHANGED
@@ -4,6 +4,7 @@ module Einhorn
4
4
  module Event
5
5
  @@loopbreak_reader = nil
6
6
  @@loopbreak_writer = nil
7
+ @@signal_actions = []
7
8
  @@readable = {}
8
9
  @@writeable = {}
9
10
  @@timers = {}
@@ -47,6 +48,10 @@ module Einhorn
47
48
  end
48
49
  end
49
50
 
51
+ def self.register_signal_action(&blk)
52
+ @@signal_actions << blk
53
+ end
54
+
50
55
  def self.register_readable(reader)
51
56
  @@readable[reader.to_io] ||= Set.new
52
57
  @@readable[reader.to_io] << reader
@@ -95,6 +100,7 @@ module Einhorn
95
100
  end
96
101
 
97
102
  def self.loop_once
103
+ run_signal_actions
98
104
  run_selectables
99
105
  run_timers
100
106
  end
@@ -108,6 +114,16 @@ module Einhorn
108
114
  end
109
115
  end
110
116
 
117
+ def self.run_signal_actions
118
+ # Note thah @@signal_actions can be mutated in the signal
119
+ # handlers. Since it's just an array we push to/shift from, we
120
+ # can be sure there's no race (such as adding hash keys during
121
+ # iteration.)
122
+ while blk = @@signal_actions.shift
123
+ blk.call
124
+ end
125
+ end
126
+
111
127
  def self.run_selectables
112
128
  time = timeout
113
129
  Einhorn.log_debug("Loop timeout is #{time.inspect}")
@@ -1,3 +1,3 @@
1
1
  module Einhorn
2
- VERSION = '0.4.5'
2
+ VERSION = '0.4.6'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: einhorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-19 00:00:00.000000000 Z
12
+ date: 2013-03-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake