servolux 0.12.0 → 0.13.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -3
- data/History.txt +24 -0
- data/lib/servolux.rb +1 -1
- data/lib/servolux/child.rb +2 -2
- data/lib/servolux/piper.rb +4 -2
- data/lib/servolux/prefork.rb +30 -3
- data/lib/servolux/server.rb +47 -7
- data/lib/servolux/version.rb +1 -1
- data/script/bootstrap +1 -1
- data/spec/prefork_spec.rb +36 -30
- data/spec/server_spec.rb +61 -32
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e69a68c60d72f0b63d0f72ed875dc7f4521e202
|
|
4
|
+
data.tar.gz: b172073acb33a563d4050f30674b3123c2d05301
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48c6f53a3ee9f8a5f7055e87bb27bbbf359e3c6a8c16e7969ac8b118a3d87441235e98d1253a7e76bae0a89c92cdd67ab2f107ac3c4df493a0413e48e4aa0678
|
|
7
|
+
data.tar.gz: 1e91faba8537394ecc2b5f3a856261f33e061b26dda3e4e9b449a24fc946b88da4de5fd3466679f0b4cf768a27c0196e2e4aaa60560f51e64446a1d02305b00d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/History.txt
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
== 0.13.0 / 2017-03-18
|
|
2
|
+
|
|
3
|
+
* Minor Enhancements
|
|
4
|
+
* Using a "self pipe" for signal handling in the Server
|
|
5
|
+
* Bug Fixes
|
|
6
|
+
* Test cleanup
|
|
7
|
+
* Better cleanup of child processes across the board
|
|
8
|
+
|
|
9
|
+
== 0.12.0 / 2015-06-07
|
|
10
|
+
|
|
11
|
+
* Minor Enhancements
|
|
12
|
+
* Adding support for a `PidFile` class [pr #19]
|
|
13
|
+
* Bug Fixes
|
|
14
|
+
|
|
15
|
+
== 0.11.0 / 2015-05-29
|
|
16
|
+
|
|
17
|
+
* Minor Enhancements
|
|
18
|
+
* Fixing server shutdown and signal handling in Ruby 2.0 and up [pr #16]
|
|
19
|
+
* Improving error handling [pr #17]
|
|
20
|
+
* Added worker options [pr #18]
|
|
21
|
+
* Added a `boostrap` script for easier development
|
|
22
|
+
* Bug Fixes
|
|
23
|
+
* Typo and documentation fixes
|
|
24
|
+
|
|
1
25
|
== 0.10.0 / 2012-02-18
|
|
2
26
|
|
|
3
27
|
* Minor Enhancements
|
data/lib/servolux.rb
CHANGED
|
@@ -37,6 +37,6 @@ module Servolux
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
%w[version
|
|
40
|
+
%w[version threaded child daemon null_logger pid_file piper prefork server].each do |lib|
|
|
41
41
|
require Servolux.libpath('servolux', lib)
|
|
42
42
|
end
|
data/lib/servolux/child.rb
CHANGED
|
@@ -149,7 +149,7 @@ class Servolux::Child
|
|
|
149
149
|
# the child process is not running.
|
|
150
150
|
#
|
|
151
151
|
def wait( flags = 0 )
|
|
152
|
-
return if @
|
|
152
|
+
return if @pid.nil?
|
|
153
153
|
_, @status = Process.wait2(@pid, flags) unless @status
|
|
154
154
|
exitstatus
|
|
155
155
|
end
|
|
@@ -160,7 +160,7 @@ class Servolux::Child
|
|
|
160
160
|
# @return [Boolean]
|
|
161
161
|
#
|
|
162
162
|
def alive?
|
|
163
|
-
return if @
|
|
163
|
+
return if @pid.nil?
|
|
164
164
|
wait(Process::WNOHANG|Process::WUNTRACED)
|
|
165
165
|
Process.kill(0, @pid)
|
|
166
166
|
true
|
data/lib/servolux/piper.rb
CHANGED
|
@@ -69,7 +69,9 @@ class Servolux::Piper
|
|
|
69
69
|
piper.parent {
|
|
70
70
|
pid = piper.gets
|
|
71
71
|
raise ::Servolux::Error, 'Could not get the child PID.' if pid.nil?
|
|
72
|
-
|
|
72
|
+
|
|
73
|
+
piper.wait # reap the child process
|
|
74
|
+
piper.instance_variable_set(:@child_pid, pid) # adopt the grandchild
|
|
73
75
|
}
|
|
74
76
|
piper.child {
|
|
75
77
|
Process.setsid # Become session leader.
|
|
@@ -358,7 +360,7 @@ class Servolux::Piper
|
|
|
358
360
|
wait(Process::WNOHANG|Process::WUNTRACED)
|
|
359
361
|
Process.kill(0, @child_pid)
|
|
360
362
|
true
|
|
361
|
-
rescue Errno::ESRCH, Errno::ENOENT
|
|
363
|
+
rescue Errno::ESRCH, Errno::ENOENT, Errno::ECHILD
|
|
362
364
|
false
|
|
363
365
|
end
|
|
364
366
|
|
data/lib/servolux/prefork.rb
CHANGED
|
@@ -209,7 +209,7 @@ class Servolux::Prefork
|
|
|
209
209
|
# @return [Prefork] self
|
|
210
210
|
#
|
|
211
211
|
def reap
|
|
212
|
-
@workers.each { |worker| worker.
|
|
212
|
+
@workers.each { |worker| worker.reap }
|
|
213
213
|
self
|
|
214
214
|
end
|
|
215
215
|
|
|
@@ -261,7 +261,7 @@ class Servolux::Prefork
|
|
|
261
261
|
# Remove workers that are no longer alive from the worker pool
|
|
262
262
|
#
|
|
263
263
|
def prune_workers
|
|
264
|
-
new_workers = @workers.find_all { |w| w.alive? }
|
|
264
|
+
new_workers = @workers.find_all { |w| w.reap.alive? }
|
|
265
265
|
@workers = new_workers
|
|
266
266
|
end
|
|
267
267
|
|
|
@@ -375,6 +375,7 @@ private
|
|
|
375
375
|
@thread = nil
|
|
376
376
|
@piper = nil
|
|
377
377
|
@error = nil
|
|
378
|
+
@pid_list = []
|
|
378
379
|
end
|
|
379
380
|
|
|
380
381
|
# Start this worker. A new process will be forked, and the code supplied
|
|
@@ -383,6 +384,7 @@ private
|
|
|
383
384
|
# @return [Worker] self
|
|
384
385
|
#
|
|
385
386
|
def start
|
|
387
|
+
@pid_list << @piper.pid if @piper
|
|
386
388
|
@error = nil
|
|
387
389
|
@piper = ::Servolux::Piper.new('rw', :timeout => @timeout)
|
|
388
390
|
@piper.parent? ? parent : child
|
|
@@ -414,7 +416,7 @@ private
|
|
|
414
416
|
#
|
|
415
417
|
def wait
|
|
416
418
|
return if @piper.nil? or @piper.child?
|
|
417
|
-
@piper.wait(Process::
|
|
419
|
+
@piper.wait(Process::WUNTRACED)
|
|
418
420
|
end
|
|
419
421
|
|
|
420
422
|
# Send this given _signal_ to the child process. The default signal is
|
|
@@ -444,6 +446,31 @@ private
|
|
|
444
446
|
@piper.alive?
|
|
445
447
|
end
|
|
446
448
|
|
|
449
|
+
# Internal: Attempt to reap any child processes spawned by this worker. If a
|
|
450
|
+
# child has exited, then we remove it from our PID list.
|
|
451
|
+
#
|
|
452
|
+
# @return [Worker] this worker instance.
|
|
453
|
+
def reap
|
|
454
|
+
@piper.alive? unless @piper.nil?
|
|
455
|
+
@pid_list.dup.each do |pid|
|
|
456
|
+
@pid_list.delete(pid) if reap?(pid)
|
|
457
|
+
end
|
|
458
|
+
self
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
# Internal: Check the return status of the given child PID. This will reap
|
|
462
|
+
# the process from the kernel process table if the child has exited.
|
|
463
|
+
#
|
|
464
|
+
# @return [Boolean] true if the PID has exited; false otherwise.
|
|
465
|
+
def reap?(pid)
|
|
466
|
+
_, cstatus = Process.wait2(pid, Process::WNOHANG|Process::WUNTRACED)
|
|
467
|
+
return true if cstatus
|
|
468
|
+
Process.kill(0, pid)
|
|
469
|
+
false
|
|
470
|
+
rescue Errno::ESRCH, Errno::ENOENT, Errno::ECHILD
|
|
471
|
+
true
|
|
472
|
+
end
|
|
473
|
+
|
|
447
474
|
# Returns +true+ if communication with the child process timed out.
|
|
448
475
|
# Returns +nil+ if the child process has not been started.
|
|
449
476
|
#
|
data/lib/servolux/server.rb
CHANGED
|
@@ -193,6 +193,7 @@ class Servolux::Server
|
|
|
193
193
|
wait_for_shutdown if wait
|
|
194
194
|
ensure
|
|
195
195
|
pid_file.delete
|
|
196
|
+
halt_signal_processing
|
|
196
197
|
end
|
|
197
198
|
return self
|
|
198
199
|
end
|
|
@@ -259,21 +260,60 @@ class Servolux::Server
|
|
|
259
260
|
|
|
260
261
|
private
|
|
261
262
|
|
|
263
|
+
def halt_signal_processing
|
|
264
|
+
if defined?(@wr) && !@wr.nil? && !@wr.closed?
|
|
265
|
+
@queue << :halt
|
|
266
|
+
@wr.write("!")
|
|
267
|
+
@wr.flush
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
262
271
|
def trap_signals
|
|
272
|
+
@queue = []
|
|
273
|
+
@rd, @wr = IO.pipe
|
|
274
|
+
|
|
263
275
|
SIGNALS.each do |sig|
|
|
264
276
|
method = sig.downcase.to_sym
|
|
265
277
|
if self.respond_to? method
|
|
266
278
|
Signal.trap(sig) do
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
end
|
|
279
|
+
begin
|
|
280
|
+
@queue << method
|
|
281
|
+
@wr.write_nonblock("!")
|
|
282
|
+
rescue StandardError => err
|
|
283
|
+
logger.error "Exception in signal handler: #{method}"
|
|
284
|
+
logger.error err
|
|
274
285
|
end
|
|
275
286
|
end
|
|
276
287
|
end
|
|
277
288
|
end
|
|
289
|
+
|
|
290
|
+
Thread.new {
|
|
291
|
+
:run while process_signals
|
|
292
|
+
@rd.close if !@rd.nil? && !@rd.closed?
|
|
293
|
+
@wr.close if !@wr.nil? && !@wr.closed?
|
|
294
|
+
logger.info "Signal processing thread has stopped"
|
|
295
|
+
}
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def process_signals
|
|
299
|
+
IO.select([@rd])
|
|
300
|
+
@rd.read_nonblock(42)
|
|
301
|
+
|
|
302
|
+
while !@queue.empty?
|
|
303
|
+
method = @queue.shift
|
|
304
|
+
next if method.nil?
|
|
305
|
+
return false if method == :halt
|
|
306
|
+
|
|
307
|
+
self.send(method)
|
|
308
|
+
end
|
|
309
|
+
return true
|
|
310
|
+
rescue IO::WaitReadable
|
|
311
|
+
return true
|
|
312
|
+
rescue IOError, EOFError, Errno::EBADF
|
|
313
|
+
return false
|
|
314
|
+
rescue StandardError => err
|
|
315
|
+
logger.error "Exception in signal handler: #{method}"
|
|
316
|
+
logger.error err
|
|
317
|
+
return false
|
|
278
318
|
end
|
|
279
319
|
end
|
data/lib/servolux/version.rb
CHANGED
data/script/bootstrap
CHANGED
data/spec/prefork_spec.rb
CHANGED
|
@@ -21,14 +21,17 @@ describe Servolux::Prefork do
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def alive?( pid )
|
|
24
|
-
_, cstatus = Process.wait2( pid, Process::WNOHANG )
|
|
25
|
-
return false if cstatus
|
|
26
24
|
Process.kill(0, pid)
|
|
27
25
|
true
|
|
28
26
|
rescue Errno::ESRCH, Errno::ENOENT, Errno::ECHILD
|
|
29
27
|
false
|
|
30
28
|
end
|
|
31
29
|
|
|
30
|
+
def wait_until( seconds = 5 )
|
|
31
|
+
start = Time.now
|
|
32
|
+
sleep 0.250 until ((Time.now - start) > seconds) || yield
|
|
33
|
+
end
|
|
34
|
+
|
|
32
35
|
before :all do
|
|
33
36
|
tmp = Tempfile.new 'servolux-prefork'
|
|
34
37
|
@path = tmp.path; tmp.unlink
|
|
@@ -65,8 +68,8 @@ describe Servolux::Prefork do
|
|
|
65
68
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
66
69
|
@prefork.start 1
|
|
67
70
|
ary = workers
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
72
|
+
wait_until { worker_count >= 1 }
|
|
70
73
|
|
|
71
74
|
ary = Dir.glob(@glob)
|
|
72
75
|
expect(ary.length).to eq(1)
|
|
@@ -77,8 +80,8 @@ describe Servolux::Prefork do
|
|
|
77
80
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
78
81
|
@prefork.start 8
|
|
79
82
|
ary = workers
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
84
|
+
wait_until { worker_count >= 8 }
|
|
82
85
|
|
|
83
86
|
ary = Dir.glob(@glob)
|
|
84
87
|
expect(ary.length).to eq(8)
|
|
@@ -91,14 +94,14 @@ describe Servolux::Prefork do
|
|
|
91
94
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
92
95
|
@prefork.start 3
|
|
93
96
|
ary = workers
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
98
|
+
wait_until { worker_count >= 3 }
|
|
96
99
|
|
|
97
100
|
ary = Dir.glob(@glob)
|
|
98
101
|
expect(ary.length).to eq(3)
|
|
99
102
|
|
|
100
103
|
@prefork.stop
|
|
101
|
-
|
|
104
|
+
wait_until { Dir.glob(@glob).length == 0 }
|
|
102
105
|
workers.each { |w| w.wait rescue nil }
|
|
103
106
|
|
|
104
107
|
rv = workers.all? { |w| !w.alive? }
|
|
@@ -109,13 +112,14 @@ describe Servolux::Prefork do
|
|
|
109
112
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
110
113
|
@prefork.start 2
|
|
111
114
|
ary = workers
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
116
|
+
wait_until { worker_count >= 2 }
|
|
114
117
|
|
|
115
118
|
pid = pids.last
|
|
116
119
|
ary.last.signal 'HUP'
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
wait_until { !alive? pid }
|
|
121
|
+
@prefork.reap
|
|
122
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
119
123
|
|
|
120
124
|
expect(pid).not_to eq(pids.last)
|
|
121
125
|
end
|
|
@@ -124,17 +128,19 @@ describe Servolux::Prefork do
|
|
|
124
128
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
125
129
|
@prefork.start 2
|
|
126
130
|
ary = workers
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
132
|
+
wait_until { worker_count >= 2 }
|
|
129
133
|
|
|
130
134
|
pid = pids.last
|
|
131
135
|
ary.last.signal 'TERM'
|
|
132
136
|
|
|
133
|
-
|
|
137
|
+
wait_until { !alive? pid }
|
|
138
|
+
@prefork.reap
|
|
139
|
+
|
|
134
140
|
@prefork.each_worker do |worker|
|
|
135
141
|
worker.start unless worker.alive?
|
|
136
142
|
end
|
|
137
|
-
|
|
143
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
138
144
|
expect(pid).not_to eq(pids.last)
|
|
139
145
|
end
|
|
140
146
|
|
|
@@ -142,12 +148,12 @@ describe Servolux::Prefork do
|
|
|
142
148
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
143
149
|
@prefork.start 2
|
|
144
150
|
ary = workers
|
|
145
|
-
|
|
146
|
-
|
|
151
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
152
|
+
wait_until { worker_count >= 2 }
|
|
147
153
|
|
|
148
154
|
|
|
149
155
|
@prefork.add_workers( 2 )
|
|
150
|
-
|
|
156
|
+
wait_until { worker_count >= 4 }
|
|
151
157
|
expect(workers.size).to eq(4)
|
|
152
158
|
end
|
|
153
159
|
|
|
@@ -155,11 +161,11 @@ describe Servolux::Prefork do
|
|
|
155
161
|
@prefork = Servolux::Prefork.new :module => @worker, :max_workers => 3, :config => {:path => @path}
|
|
156
162
|
@prefork.start 2
|
|
157
163
|
ary = workers
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
165
|
+
wait_until { worker_count >= 2 }
|
|
160
166
|
|
|
161
167
|
@prefork.add_workers( 2 )
|
|
162
|
-
|
|
168
|
+
wait_until { worker_count >= 3 }
|
|
163
169
|
expect(workers.size).to eq(3)
|
|
164
170
|
end
|
|
165
171
|
|
|
@@ -167,15 +173,15 @@ describe Servolux::Prefork do
|
|
|
167
173
|
@prefork = Servolux::Prefork.new :module => @worker, :config => {:path => @path}
|
|
168
174
|
@prefork.start 2
|
|
169
175
|
ary = workers
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
177
|
+
wait_until { worker_count >= 2 }
|
|
172
178
|
|
|
173
179
|
@prefork.add_workers( 2 )
|
|
174
|
-
|
|
180
|
+
wait_until { worker_count >= 3 }
|
|
175
181
|
expect(workers.size).to eq(4)
|
|
176
182
|
|
|
177
183
|
workers[0].stop
|
|
178
|
-
|
|
184
|
+
wait_until { !workers[0].alive? }
|
|
179
185
|
|
|
180
186
|
@prefork.prune_workers
|
|
181
187
|
expect(workers.size).to eq(3)
|
|
@@ -185,11 +191,11 @@ describe Servolux::Prefork do
|
|
|
185
191
|
@prefork = Servolux::Prefork.new :module => @worker, :min_workers => 3, :config => {:path => @path}
|
|
186
192
|
@prefork.start 1
|
|
187
193
|
ary = workers
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
wait_until { ary.all? { |w| w.alive? } }
|
|
195
|
+
wait_until { worker_count >= 1 }
|
|
190
196
|
|
|
191
197
|
@prefork.ensure_worker_pool_size
|
|
192
|
-
|
|
198
|
+
wait_until { worker_count >= 3 }
|
|
193
199
|
expect(workers.size).to eq(3)
|
|
194
200
|
end
|
|
195
201
|
end
|
data/spec/server_spec.rb
CHANGED
|
@@ -5,7 +5,11 @@ describe Servolux::Server do
|
|
|
5
5
|
|
|
6
6
|
def wait_until( seconds = 5 )
|
|
7
7
|
start = Time.now
|
|
8
|
-
sleep 0.250 until (Time.now - start) > seconds
|
|
8
|
+
sleep 0.250 until ((Time.now - start) > seconds) || yield
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def readlog
|
|
12
|
+
@log_output.readline
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
base = Class.new(Servolux::Server) do
|
|
@@ -23,62 +27,63 @@ describe Servolux::Server do
|
|
|
23
27
|
after :each do
|
|
24
28
|
@server.shutdown
|
|
25
29
|
@server.wait_for_shutdown
|
|
30
|
+
wait_until { @t.status == false } if @t && @t.alive?
|
|
26
31
|
end
|
|
27
32
|
|
|
28
33
|
it 'generates a PID file' do
|
|
29
34
|
expect(@server.pid_file).to_not exist
|
|
30
35
|
|
|
31
|
-
t = Thread.new {@server.startup}
|
|
32
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
36
|
+
@t = Thread.new {@server.startup}
|
|
37
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
33
38
|
expect(@server.pid_file).to exist
|
|
34
39
|
|
|
35
40
|
@server.shutdown
|
|
36
|
-
wait_until { t.status == false }
|
|
41
|
+
wait_until { @t.status == false }
|
|
37
42
|
expect(@server.pid_file).to_not exist
|
|
38
43
|
end
|
|
39
44
|
|
|
40
45
|
it 'generates a PID file with mode rw-r----- by default' do
|
|
41
|
-
t = Thread.new {@server.startup}
|
|
42
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
46
|
+
@t = Thread.new {@server.startup}
|
|
47
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
43
48
|
expect(@server.pid_file).to exist
|
|
44
49
|
|
|
45
|
-
expect(
|
|
46
|
-
expect(
|
|
50
|
+
expect(readlog.chomp).to eq(%q(DEBUG Servolux : Writing pid file "./test_server.pid"))
|
|
51
|
+
expect(readlog.chomp).to eq(%q(DEBUG Servolux : Starting))
|
|
47
52
|
|
|
48
53
|
filename = @server.pid_file.filename
|
|
49
54
|
mode = File.stat(filename).mode & 0777
|
|
50
55
|
expect(mode).to eq(0640)
|
|
51
56
|
|
|
52
57
|
@server.shutdown
|
|
53
|
-
wait_until { t.status == false }
|
|
58
|
+
wait_until { @t.status == false }
|
|
54
59
|
expect(@server.pid_file).to_not exist
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
it 'generates PID file with the specified permissions' do
|
|
58
63
|
@server.pid_file.mode = 0400
|
|
59
|
-
t = Thread.new {@server.startup}
|
|
60
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
64
|
+
@t = Thread.new {@server.startup}
|
|
65
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
61
66
|
expect(@server.pid_file).to exist
|
|
62
67
|
|
|
63
|
-
expect(
|
|
64
|
-
expect(
|
|
68
|
+
expect(readlog.chomp).to eq(%q(DEBUG Servolux : Writing pid file "./test_server.pid"))
|
|
69
|
+
expect(readlog.chomp).to eq(%q(DEBUG Servolux : Starting))
|
|
65
70
|
|
|
66
71
|
filename = @server.pid_file.filename
|
|
67
72
|
mode = File.stat(filename).mode & 0777
|
|
68
73
|
expect(mode).to eq(0400)
|
|
69
74
|
|
|
70
75
|
@server.shutdown
|
|
71
|
-
wait_until { t.status == false }
|
|
76
|
+
wait_until { @t.status == false }
|
|
72
77
|
expect(@server.pid_file).to_not exist
|
|
73
78
|
end
|
|
74
79
|
|
|
75
80
|
it 'shuts down gracefully when signaled' do
|
|
76
|
-
t = Thread.new {@server.startup}
|
|
77
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
81
|
+
@t = Thread.new {@server.startup}
|
|
82
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
78
83
|
expect(@server).to be_running
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
wait_until { t.status == false }
|
|
85
|
+
Process.kill 'SIGINT', $$
|
|
86
|
+
wait_until { @t.status == false }
|
|
82
87
|
expect(@server).to_not be_running
|
|
83
88
|
end
|
|
84
89
|
|
|
@@ -89,31 +94,31 @@ describe Servolux::Server do
|
|
|
89
94
|
def usr2() logger.info 'usr2 was called'; end
|
|
90
95
|
end
|
|
91
96
|
|
|
92
|
-
t = Thread.new {@server.startup}
|
|
93
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
94
|
-
|
|
95
|
-
expect(
|
|
97
|
+
@t = Thread.new {@server.startup}
|
|
98
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
99
|
+
readlog
|
|
100
|
+
expect(readlog.strip).to eq('DEBUG Servolux : Starting')
|
|
96
101
|
|
|
97
102
|
line = nil
|
|
98
103
|
Process.kill 'SIGUSR1', $$
|
|
99
|
-
wait_until { line =
|
|
104
|
+
wait_until { line = readlog }
|
|
100
105
|
expect(line).to_not be_nil
|
|
101
106
|
expect(line.strip).to eq('INFO Servolux : usr1 was called')
|
|
102
107
|
|
|
103
108
|
line = nil
|
|
104
109
|
Process.kill 'SIGHUP', $$
|
|
105
|
-
wait_until { line =
|
|
110
|
+
wait_until { line = readlog }
|
|
106
111
|
expect(line).to_not be_nil
|
|
107
112
|
expect(line.strip).to eq('INFO Servolux : hup was called')
|
|
108
113
|
|
|
109
114
|
line = nil
|
|
110
115
|
Process.kill 'SIGUSR2', $$
|
|
111
|
-
wait_until { line =
|
|
116
|
+
wait_until { line = readlog }
|
|
112
117
|
expect(line).to_not be_nil
|
|
113
118
|
expect(line.strip).to eq('INFO Servolux : usr2 was called')
|
|
114
119
|
|
|
115
120
|
Process.kill 'SIGTERM', $$
|
|
116
|
-
wait_until { t.status == false }
|
|
121
|
+
wait_until { @t.status == false }
|
|
117
122
|
expect(@server).to_not be_running
|
|
118
123
|
end
|
|
119
124
|
|
|
@@ -122,20 +127,44 @@ describe Servolux::Server do
|
|
|
122
127
|
def usr2() raise 'Ooops!'; end
|
|
123
128
|
end
|
|
124
129
|
|
|
125
|
-
t = Thread.new {@server.startup}
|
|
126
|
-
wait_until { @server.running? and t.status == 'sleep' }
|
|
127
|
-
|
|
128
|
-
expect(
|
|
130
|
+
@t = Thread.new {@server.startup}
|
|
131
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
132
|
+
readlog
|
|
133
|
+
expect(readlog.strip).to eq('DEBUG Servolux : Starting')
|
|
129
134
|
|
|
130
135
|
line = nil
|
|
131
136
|
Process.kill 'SIGUSR2', $$
|
|
132
|
-
wait_until { line =
|
|
137
|
+
wait_until { line = readlog }
|
|
133
138
|
expect(line).to_not be_nil
|
|
134
139
|
expect(line.strip).to eq('ERROR Servolux : Exception in signal handler: usr2')
|
|
135
140
|
|
|
136
141
|
line = nil
|
|
137
|
-
wait_until { line =
|
|
142
|
+
wait_until { line = readlog }
|
|
138
143
|
expect(line).to_not be_nil
|
|
139
144
|
expect(line.strip).to eq('ERROR Servolux : <RuntimeError> Ooops!')
|
|
140
145
|
end
|
|
146
|
+
|
|
147
|
+
it 'logs when the signal handler thread exits' do
|
|
148
|
+
class << @server
|
|
149
|
+
def hup() logger.info 'hup was called'; end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
@t = Thread.new {@server.startup}
|
|
153
|
+
wait_until { @server.running? and @t.status == 'sleep' }
|
|
154
|
+
readlog
|
|
155
|
+
expect(readlog.strip).to eq('DEBUG Servolux : Starting')
|
|
156
|
+
|
|
157
|
+
line = nil
|
|
158
|
+
@server.__send__(:halt_signal_processing)
|
|
159
|
+
wait_until { line = readlog }
|
|
160
|
+
expect(line).to_not be_nil
|
|
161
|
+
expect(line.strip).to eq('INFO Servolux : Signal processing thread has stopped')
|
|
162
|
+
|
|
163
|
+
line = nil
|
|
164
|
+
Process.kill 'SIGHUP', $$
|
|
165
|
+
wait_until { line = readlog }
|
|
166
|
+
expect(line).to_not be_nil
|
|
167
|
+
expect(line.strip).to eq('ERROR Servolux : Exception in signal handler: hup')
|
|
168
|
+
expect(readlog.strip).to eq('ERROR Servolux : <IOError> closed stream')
|
|
169
|
+
end
|
|
141
170
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: servolux
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tim Pease
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2017-03-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bones-rspec
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 3.8.
|
|
61
|
+
version: 3.8.4
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 3.8.
|
|
68
|
+
version: 3.8.4
|
|
69
69
|
description: |-
|
|
70
70
|
Serv-O-Lux is a collection of Ruby classes that are useful for daemon and
|
|
71
71
|
process management, and for writing your own Ruby services. The code is well
|
|
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
127
127
|
version: '0'
|
|
128
128
|
requirements: []
|
|
129
129
|
rubyforge_project: servolux
|
|
130
|
-
rubygems_version: 2.
|
|
130
|
+
rubygems_version: 2.6.8
|
|
131
131
|
signing_key:
|
|
132
132
|
specification_version: 4
|
|
133
133
|
summary: A collection of tools for working with processes
|