servolux 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -1
- data/README.rdoc +25 -4
- data/lib/servolux.rb +1 -1
- data/lib/servolux/child.rb +96 -10
- data/lib/servolux/daemon.rb +1 -0
- data/spec/child_spec.rb +51 -0
- metadata +5 -4
data/History.txt
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
== 0.
|
1
|
+
== 0.5.0 / 2009-06-30
|
2
|
+
|
3
|
+
* 2 Minor Enchancements
|
4
|
+
* Added tests for the Child class
|
5
|
+
* Updating documentation in preperation for a release
|
6
|
+
|
7
|
+
== 0.4.0 / 2009-06-29
|
2
8
|
|
3
9
|
* 1 Minor Enhancement
|
4
10
|
* Added a "Child" class for working with child processes
|
data/README.rdoc
CHANGED
@@ -4,18 +4,39 @@
|
|
4
4
|
|
5
5
|
=== DESCRIPTION:
|
6
6
|
|
7
|
-
|
7
|
+
Serv-O-Lux is a collection of Ruby classes that are useful for daemon and
|
8
|
+
process management, and for writing your own Ruby services. The code is well
|
9
|
+
documented and tested. It works with Ruby and JRuby supporing both 1.8 and 1.9
|
10
|
+
interpreters.
|
8
11
|
|
9
12
|
=== FEATURES:
|
10
13
|
|
11
|
-
|
14
|
+
Servolux::Threaded -- when included into your own class, it gives you an
|
15
|
+
activity thread that will run some code at a regular interval. Provides methods
|
16
|
+
to start and stop the thread, report on the running state, and join the thread
|
17
|
+
to wait for it to complete.
|
12
18
|
|
13
|
-
|
19
|
+
Servolux::Server -- a template server class that handles the mundane work of
|
20
|
+
creating / deleting a PID file, reporting running state, logging errors,
|
21
|
+
starting the service, and gracefully shutting down the service.
|
14
22
|
|
23
|
+
Servolux::Piper -- an extension of the standard Ruby fork method that opens a
|
24
|
+
pipe for communication between parent and child processes. Ruby objects are
|
25
|
+
passed between parent and child allowing, for example, exceptions in the child
|
26
|
+
process to be passed to the parent and raised there.
|
27
|
+
|
28
|
+
Servolux::Daemon -- a robust class for starting and stopping daemon processes.
|
29
|
+
|
30
|
+
Servolux::Child -- adds some much needed funtionality to child processes
|
31
|
+
created via Ruby's IO#popen method. Specifically, a timeout thread is used to
|
32
|
+
signal the child process to die if it does not exit in a given amount of time.
|
33
|
+
|
34
|
+
|
35
|
+
All the documentation is available online at http://codeforpeople.rubyforge.org/servolux
|
15
36
|
|
16
37
|
=== INSTALL:
|
17
38
|
|
18
|
-
gem install servolux
|
39
|
+
gem install servolux
|
19
40
|
|
20
41
|
=== LICENSE:
|
21
42
|
|
data/lib/servolux.rb
CHANGED
data/lib/servolux/child.rb
CHANGED
@@ -1,5 +1,41 @@
|
|
1
1
|
|
2
|
+
# == Synopsis
|
3
|
+
# Manage a child process spawned via IO#popen and provide a timeout
|
4
|
+
# mechanism to kill the process after some amount time.
|
2
5
|
#
|
6
|
+
# == Details
|
7
|
+
# Ruby provides the IO#popen method to spawn a child process and return an
|
8
|
+
# IO instance connected to the child's stdin and stdout (with stderr
|
9
|
+
# redirected to stdout). The Servolux::Child class adds to this a timeout
|
10
|
+
# thread that will signal the child process after some number of seconds.
|
11
|
+
# If the child exits cleanly before the timeout expires then no signals are
|
12
|
+
# sent to the child.
|
13
|
+
#
|
14
|
+
# A list of signals can be provided which will be sent in succession to the
|
15
|
+
# child until one of them causes the child to exit. The current Ruby thread
|
16
|
+
# suspends for a few seconds to allow each signal to be processed by the
|
17
|
+
# child. By default these signals are SIGTERM, SIGQUIT, SIGKILL and the time
|
18
|
+
# to wait between signals is four seconds.
|
19
|
+
#
|
20
|
+
# The +stop+ method is used to stop the child process (if running) and to
|
21
|
+
# reset the state of the Child instance so that it can be started again.
|
22
|
+
# Stopping the Child instance closes the IO between parent and child
|
23
|
+
# process.
|
24
|
+
#
|
25
|
+
# The +wait+ method is used to wait for the child process to exit. The
|
26
|
+
# Process::Status object is retrieved by the Child and stored as an instance
|
27
|
+
# variable. The +exitstatus+ method (and the other process related methods)
|
28
|
+
# will return non-nil values after the wait method is called.
|
29
|
+
#
|
30
|
+
# == Examples
|
31
|
+
#
|
32
|
+
# child = Servolux::Child.new(:command => 'sleep 120', :timeout => 10)
|
33
|
+
# child.start
|
34
|
+
# child.wait
|
35
|
+
#
|
36
|
+
# child.timed_out? #=> true
|
37
|
+
# child.signaled? #=> true
|
38
|
+
# child.exitstatus #=> nil
|
3
39
|
#
|
4
40
|
class Servolux::Child
|
5
41
|
|
@@ -10,29 +46,63 @@ class Servolux::Child
|
|
10
46
|
attr_reader :io
|
11
47
|
attr_reader :pid
|
12
48
|
|
49
|
+
# Create a new Child that will execute and manage the +command+ string as
|
50
|
+
# a child process.
|
51
|
+
#
|
52
|
+
# ==== Options
|
53
|
+
# * command <String>
|
54
|
+
# The command that will be executed via IO#popen.
|
13
55
|
#
|
56
|
+
# * timeout <Numeric>
|
57
|
+
# The number of seconds to wait before terminating the child process.
|
58
|
+
# No action is taken if the child process exits normally before the
|
59
|
+
# timeout expires.
|
14
60
|
#
|
15
|
-
|
16
|
-
|
61
|
+
# * signals <Array>
|
62
|
+
# A list of signals that will be sent to the child process when the
|
63
|
+
# timeout expires. The signals increase in severity with SIGKILL being
|
64
|
+
# the signal of last resort.
|
65
|
+
#
|
66
|
+
# * suspend <Numeric>
|
67
|
+
# The number of seconds to wait for the child process to respond to
|
68
|
+
# a signal before trying the next one in the list.
|
69
|
+
#
|
70
|
+
def initialize( opts = {} )
|
71
|
+
@command = opts.getopt :command
|
17
72
|
@timeout = opts.getopt :timeout
|
18
73
|
@signals = opts.getopt :signals, %w[TERM QUIT KILL]
|
19
74
|
@suspend = opts.getopt :suspend, 4
|
20
|
-
@io = @pid = @thread = @timed_out = nil
|
75
|
+
@io = @pid = @status = @thread = @timed_out = nil
|
76
|
+
yield self if block_given?
|
21
77
|
end
|
22
78
|
|
79
|
+
# Runs the +command+ string as a subprocess; the subprocess’s
|
80
|
+
# standard input and output will be connected to the returned IO object.
|
81
|
+
# The default mode for the new file object is "r", but mode may be set to
|
82
|
+
# any of the modes listed in the description for class IO.
|
23
83
|
#
|
84
|
+
# If a block is given, Ruby will run the +command+ as a child connected to
|
85
|
+
# Ruby with a pipe. Ruby’s end of the pipe will be passed as a parameter
|
86
|
+
# to the block. In this case the value of the block is returned.
|
24
87
|
#
|
25
88
|
def start( mode = 'r', &block )
|
26
89
|
start_timeout_thread if @timeout
|
27
90
|
|
28
|
-
@io
|
91
|
+
@io = IO::popen @command, mode
|
29
92
|
@pid = @io.pid
|
93
|
+
@status = nil
|
30
94
|
|
31
95
|
return block.call(@io) unless block.nil?
|
32
|
-
|
96
|
+
@io
|
33
97
|
end
|
34
98
|
|
99
|
+
# Stop the child process if it is alive. A sequence of +signals+ are sent
|
100
|
+
# to the process until it dies with SIGKILL being the signal of last
|
101
|
+
# resort.
|
35
102
|
#
|
103
|
+
# After this method returns, the IO pipe to the child will be closed and
|
104
|
+
# the stored child PID is set to +nil+. The +start+ method can be safely
|
105
|
+
# called again.
|
36
106
|
#
|
37
107
|
def stop
|
38
108
|
unless @thread.nil?
|
@@ -43,7 +113,7 @@ class Servolux::Child
|
|
43
113
|
|
44
114
|
kill if alive?
|
45
115
|
@io.close rescue nil
|
46
|
-
@io =
|
116
|
+
@io = nil
|
47
117
|
self
|
48
118
|
end
|
49
119
|
|
@@ -54,10 +124,12 @@ class Servolux::Child
|
|
54
124
|
def wait( flags = 0 )
|
55
125
|
return if @io.nil?
|
56
126
|
Process.wait(@pid, flags)
|
57
|
-
|
127
|
+
@status = $?
|
128
|
+
exitstatus
|
58
129
|
end
|
59
130
|
|
60
|
-
# Returns +true+ if the child process is alive.
|
131
|
+
# Returns +true+ if the child process is alive. Returns +nil+ if the child
|
132
|
+
# process has not been started.
|
61
133
|
#
|
62
134
|
def alive?
|
63
135
|
return if @io.nil?
|
@@ -73,10 +145,26 @@ class Servolux::Child
|
|
73
145
|
@timed_out
|
74
146
|
end
|
75
147
|
|
148
|
+
%w[coredump? exited? signaled? stopped? success? exitstatus stopsig termsig].
|
149
|
+
each { |method|
|
150
|
+
self.class_eval <<-CODE
|
151
|
+
def #{method}
|
152
|
+
return if @status.nil?
|
153
|
+
@status.#{method}
|
154
|
+
end
|
155
|
+
CODE
|
156
|
+
}
|
157
|
+
|
76
158
|
|
77
159
|
private
|
78
160
|
|
161
|
+
# Attempt to kill the child process by sending the configured +signals+
|
162
|
+
# and waiting for +suspend+ seconds between each signal; this gives the
|
163
|
+
# child time to respond to the signal.
|
79
164
|
#
|
165
|
+
# Returns +true+ if the child died. Returns +false+ if the child is still
|
166
|
+
# not dead after the last signal was sent. Returns +nil+ if the child was
|
167
|
+
# not running in the first place.
|
80
168
|
#
|
81
169
|
def kill
|
82
170
|
return if @io.nil?
|
@@ -96,8 +184,6 @@ class Servolux::Child
|
|
96
184
|
return !alive?
|
97
185
|
end
|
98
186
|
|
99
|
-
#
|
100
|
-
#
|
101
187
|
def start_timeout_thread
|
102
188
|
@timed_out = false
|
103
189
|
@thread = Thread.new(self) { |child|
|
data/lib/servolux/daemon.rb
CHANGED
data/spec/child_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
3
|
+
|
4
|
+
describe Servolux::Child do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
@child = Servolux::Child.new
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
@child.stop
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has some sensible defaults' do
|
15
|
+
@child.command.should be_nil
|
16
|
+
@child.timeout.should be_nil
|
17
|
+
@child.signals.should == %w[TERM QUIT KILL]
|
18
|
+
@child.suspend.should == 4
|
19
|
+
@child.pid.should be_nil
|
20
|
+
@child.io.should be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'starts a child process' do
|
24
|
+
@child.command = 'echo `pwd`'
|
25
|
+
@child.start
|
26
|
+
|
27
|
+
@child.pid.should_not be_nil
|
28
|
+
@child.wait
|
29
|
+
@child.io.read.strip.should == Dir.pwd
|
30
|
+
@child.success?.should be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'kills a child process after some timeout' do
|
34
|
+
@child.command = 'sleep 5; echo `pwd`'
|
35
|
+
@child.timeout = 0.25
|
36
|
+
@child.start
|
37
|
+
|
38
|
+
@child.pid.should_not be_nil
|
39
|
+
@child.wait
|
40
|
+
|
41
|
+
@child.io.read.strip.should be_empty
|
42
|
+
|
43
|
+
@child.signaled?.should be_true
|
44
|
+
@child.exited?.should be_false
|
45
|
+
@child.exitstatus.should be_nil
|
46
|
+
@child.success?.should be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# EOF
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servolux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Pease
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-30 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 2.5.0
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: Serv-O-Lux is a collection of Ruby classes that are useful for daemon and process management, and for writing your own Ruby services. The code is well documented and tested. It works with Ruby and JRuby supporing both 1.8 and 1.9 interpreters.
|
46
46
|
email: tim.pease@gmail.com
|
47
47
|
executables: []
|
48
48
|
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/servolux/piper.rb
|
62
62
|
- lib/servolux/server.rb
|
63
63
|
- lib/servolux/threaded.rb
|
64
|
+
- spec/child_spec.rb
|
64
65
|
- spec/piper_spec.rb
|
65
66
|
- spec/server_spec.rb
|
66
67
|
- spec/servolux_spec.rb
|
@@ -105,6 +106,6 @@ rubyforge_project: codeforpeople
|
|
105
106
|
rubygems_version: 1.3.1
|
106
107
|
signing_key:
|
107
108
|
specification_version: 2
|
108
|
-
summary:
|
109
|
+
summary: Serv-O-Lux is a collection of Ruby classes that are useful for daemon and process management, and for writing your own Ruby services
|
109
110
|
test_files: []
|
110
111
|
|