einhorn 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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