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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 581567ae92a495cdeb92737c979d52e6bd8cf996
4
- data.tar.gz: 0f887e81fc0a8b78e1f340578f2183b460a27ca7
3
+ metadata.gz: 2e69a68c60d72f0b63d0f72ed875dc7f4521e202
4
+ data.tar.gz: b172073acb33a563d4050f30674b3123c2d05301
5
5
  SHA512:
6
- metadata.gz: b67919d827ef8ca1e956918d631bbb2a1ffebcedf3334c4197664c674f340910c0156b6973e476f62c1030069a49332752c7847fab262ee219f633260d971e3f
7
- data.tar.gz: 4cb69e76d39fece3215048a9032bfa3904888061dc1676b818500bca238503f0659e67ee583d98efd9286caf2abc30ccf0e27b283c8deccc62b5e1ec5fe3c558
6
+ metadata.gz: 48c6f53a3ee9f8a5f7055e87bb27bbbf359e3c6a8c16e7969ac8b118a3d87441235e98d1253a7e76bae0a89c92cdd67ab2f107ac3c4df493a0413e48e4aa0678
7
+ data.tar.gz: 1e91faba8537394ecc2b5f3a856261f33e061b26dda3e4e9b449a24fc946b88da4de5fd3466679f0b4cf768a27c0196e2e4aaa60560f51e64446a1d02305b00d
data/.gitignore CHANGED
@@ -15,6 +15,7 @@ announcement.txt
15
15
  coverage
16
16
  doc
17
17
  pkg
18
+ tags
18
19
  .yardoc
19
20
  .rvmrc
20
21
  vendor
@@ -1,11 +1,15 @@
1
1
  language: ruby
2
2
 
3
+ notifications:
4
+ email: false
5
+
3
6
  before_install: "gem install bones"
4
7
  install: "rake gem:install_dependencies"
5
8
 
6
9
  script: "rake"
7
10
 
8
11
  rvm:
9
- - 1.9.3
10
- - 2.1.5
11
- - 2.2.2
12
+ - 2.1.10
13
+ - 2.2.6
14
+ - 2.3.3
15
+ - 2.4.0
@@ -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
@@ -37,6 +37,6 @@ module Servolux
37
37
  end
38
38
  end
39
39
 
40
- %w[version null_logger threaded pid_file server piper daemon child prefork].each do |lib|
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
@@ -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 @io.nil?
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 @io.nil?
163
+ return if @pid.nil?
164
164
  wait(Process::WNOHANG|Process::WUNTRACED)
165
165
  Process.kill(0, @pid)
166
166
  true
@@ -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
- piper.instance_variable_set(:@child_pid, pid)
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
 
@@ -209,7 +209,7 @@ class Servolux::Prefork
209
209
  # @return [Prefork] self
210
210
  #
211
211
  def reap
212
- @workers.each { |worker| worker.alive? }
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::WNOHANG|Process::WUNTRACED)
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
  #
@@ -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
- Thread.new do
268
- begin
269
- self.send(method)
270
- rescue StandardError => err
271
- logger.error "Exception in signal handler: #{method}"
272
- logger.error err
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
@@ -1,5 +1,5 @@
1
1
  module Servolux
2
- VERSION = "0.12.0".freeze
2
+ VERSION = "0.13.0".freeze
3
3
 
4
4
  # Returns the version string for the library.
5
5
  def self.version
@@ -2,7 +2,7 @@
2
2
 
3
3
  gem list -i bones >/dev/null 2>&1
4
4
  rc=$?
5
- if [[ $rc != 0 ]]; then
5
+ if [ "$rc" != "0" ]; then
6
6
  gem install bones
7
7
  fi
8
8
 
@@ -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
- sleep 0.1 until ary.all? { |w| w.alive? }
69
- sleep 0.1 until worker_count >= 1
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
- sleep 0.250 until ary.all? { |w| w.alive? }
81
- sleep 0.250 until worker_count >= 8
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
- sleep 0.250 until ary.all? { |w| w.alive? }
95
- sleep 0.250 until worker_count >= 3
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
- sleep 0.250 until Dir.glob(@glob).length == 0
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
- sleep 0.250 until ary.all? { |w| w.alive? }
113
- sleep 0.250 until worker_count >= 2
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
- @prefork.reap until !alive? pid
118
- sleep 0.250 until ary.all? { |w| w.alive? }
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
- sleep 0.250 until ary.all? { |w| w.alive? }
128
- sleep 0.250 until worker_count >= 2
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
- @prefork.reap until !alive? pid
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
- sleep 0.250 until ary.all? { |w| w.alive? }
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
- sleep 0.250 until ary.all? { |w| w.alive? }
146
- sleep 0.250 until worker_count >= 2
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
- sleep 0.250 until worker_count >= 4
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
- sleep 0.250 until ary.all? { |w| w.alive? }
159
- sleep 0.250 until worker_count >= 2
164
+ wait_until { ary.all? { |w| w.alive? } }
165
+ wait_until { worker_count >= 2 }
160
166
 
161
167
  @prefork.add_workers( 2 )
162
- sleep 0.250 until worker_count >= 3
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
- sleep 0.250 until ary.all? { |w| w.alive? }
171
- sleep 0.250 until worker_count >= 2
176
+ wait_until { ary.all? { |w| w.alive? } }
177
+ wait_until { worker_count >= 2 }
172
178
 
173
179
  @prefork.add_workers( 2 )
174
- sleep 0.250 until worker_count >= 3
180
+ wait_until { worker_count >= 3 }
175
181
  expect(workers.size).to eq(4)
176
182
 
177
183
  workers[0].stop
178
- sleep 0.250 while workers[0].alive?
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
- sleep 0.250 until ary.all? { |w| w.alive? }
189
- sleep 0.250 until worker_count >= 1
194
+ wait_until { ary.all? { |w| w.alive? } }
195
+ wait_until { worker_count >= 1 }
190
196
 
191
197
  @prefork.ensure_worker_pool_size
192
- sleep 0.250 until worker_count >= 3
198
+ wait_until { worker_count >= 3 }
193
199
  expect(workers.size).to eq(3)
194
200
  end
195
201
  end
@@ -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 or yield
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(@log_output.readline.chomp).to eq(%q(DEBUG Servolux : Writing pid file "./test_server.pid"))
46
- expect(@log_output.readline.chomp).to eq(%q(DEBUG Servolux : Starting))
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(@log_output.readline.chomp).to eq(%q(DEBUG Servolux : Writing pid file "./test_server.pid"))
64
- expect(@log_output.readline.chomp).to eq(%q(DEBUG Servolux : Starting))
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
- `kill -SIGINT #{$$}`
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
- @log_output.readline
95
- expect(@log_output.readline.strip).to eq('DEBUG Servolux : Starting')
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 = @log_output.readline }
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 = @log_output.readline }
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 = @log_output.readline }
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
- @log_output.readline
128
- expect(@log_output.readline.strip).to eq('DEBUG Servolux : Starting')
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 = @log_output.readline }
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 = @log_output.readline }
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.12.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: 2015-06-08 00:00:00.000000000 Z
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.3
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.3
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.2.3
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