raad 0.4.0 → 0.4.1
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.
- data/CHANGELOG.md +9 -2
- data/README.md +107 -37
- data/lib/raad/{service.rb → bootstrap.rb} +16 -16
- data/lib/raad/env.rb +21 -3
- data/lib/raad/runner.rb +15 -8
- data/lib/raad/unix_daemon.rb +7 -13
- data/lib/raad/version.rb +1 -1
- data/lib/raad.rb +1 -1
- metadata +11 -11
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,13 @@
|
|
7
7
|
- wrong exit code bug
|
8
8
|
- comments & cosmetics
|
9
9
|
|
10
|
-
# 0.4, 09-
|
10
|
+
# 0.4.0, 09-13-2011
|
11
11
|
- using SignalTrampoline for safe signal handling
|
12
|
-
- JRuby support
|
12
|
+
- JRuby support
|
13
|
+
- specs and validations for all supported rubies
|
14
|
+
- tested on MRI 1.8.7 & 1.9.2, REE 1.8.7, JRuby 1.6.4 under OSX 10.6.8 and Linux Ubuntu 10.04
|
15
|
+
|
16
|
+
# 0.4.1, 09-22-2011
|
17
|
+
- allow arbitrary environment name
|
18
|
+
- added Raad.stopped?
|
19
|
+
- avoid calling stop multiple times, https://github.com/praized/raad/issues/3
|
data/README.md
CHANGED
@@ -2,56 +2,116 @@
|
|
2
2
|
|
3
3
|
Raad - Ruby as a daemon lightweight service wrapper.
|
4
4
|
|
5
|
-
Raad is a non-intrusive, lightweight, simple Ruby daemon wrapper. Basically
|
6
|
-
the start and stop methods, can be used seamlessly as a daemon or a normal console app.
|
5
|
+
Raad is a non-intrusive, lightweight, simple Ruby daemon wrapper. Basically any class which implements
|
6
|
+
the `start` and `stop` methods, can be used seamlessly as a daemon or a normal console app.
|
7
7
|
|
8
|
-
Raad
|
9
|
-
|
8
|
+
Raad **deamonizing** will work the same way for both MRI Ruby and **JRuby**, without
|
9
|
+
modification in your code.
|
10
|
+
|
11
|
+
Raad provides basic daemon control using the start/stop commands. Your code can also use the Raad
|
12
|
+
logging module and benefit easy log file output while daemonized.
|
10
13
|
|
11
14
|
## Installation
|
12
15
|
|
13
16
|
### Gem
|
14
|
-
|
17
|
+
|
18
|
+
``` sh
|
19
|
+
$ gem install raad
|
20
|
+
```
|
15
21
|
|
16
22
|
### Bundler
|
17
23
|
#### Latest from github
|
24
|
+
|
25
|
+
``` sh
|
18
26
|
gem "raad", :git => "git://github.com/praized/raad.git", :branch => "master"
|
27
|
+
```
|
19
28
|
|
20
29
|
#### Released gem
|
30
|
+
|
31
|
+
``` bash
|
21
32
|
gem "raad", "~> 0.4.0"
|
33
|
+
```
|
22
34
|
|
23
35
|
## Example
|
24
|
-
Create a class with a start and a stop method. Just by requiring 'raad', your class will be
|
25
|
-
wrapped by Raad and daemonizable
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
def stop
|
39
|
-
@stopped = true
|
40
|
-
Raad::Logger.info("simple_daemon stopped")
|
41
|
-
end
|
36
|
+
Create a class with a `start` and a `stop` method. Just by requiring 'raad', your class will be
|
37
|
+
wrapped by Raad and become **daemonizable**.
|
38
|
+
|
39
|
+
``` ruby
|
40
|
+
require 'rubygems'
|
41
|
+
require 'raad'
|
42
|
+
|
43
|
+
class SimpleDaemon
|
44
|
+
def start
|
45
|
+
while !Raad.stopped?
|
46
|
+
Raad::Logger.info("simple_daemon running")
|
47
|
+
sleep(1)
|
42
48
|
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def stop
|
52
|
+
Raad::Logger.info("simple_daemon stopped")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
- run it in console mode, `^C` will stop it, calling the stop method
|
57
|
+
|
58
|
+
``` sh
|
59
|
+
$ ruby simple_daemon.rb start
|
60
|
+
```
|
61
|
+
- run it daemonized, by default `./simple_daemon.log` and `./simple_daemon.pid` will be created
|
43
62
|
|
44
|
-
|
45
|
-
|
63
|
+
``` sh
|
64
|
+
$ ruby simple_daemon.rb -d start
|
65
|
+
```
|
46
66
|
|
47
|
-
|
48
|
-
$ ruby simple_daemon.rb -d start
|
67
|
+
- stop daemon, removing `./simple_daemon.pid`
|
49
68
|
|
50
|
-
|
51
|
-
|
69
|
+
``` sh
|
70
|
+
$ ruby simple_daemon.rb stop
|
71
|
+
```
|
52
72
|
|
53
73
|
## Documentation
|
54
74
|
|
75
|
+
### Introduction
|
76
|
+
|
77
|
+
By requiring 'raad' in your class, it will automagically be wrapped by the Raad bootstrap code.
|
78
|
+
When running your class file with the `start` parameter, Raad will call your class `start` method.
|
79
|
+
|
80
|
+
The `start` method **should not return** unless your service has completed its work or has been
|
81
|
+
instructed to stop.
|
82
|
+
|
83
|
+
There are two ways to know when your service has been instructed to stop:
|
84
|
+
|
85
|
+
* the `stop` method of your class will be called if it is defined
|
86
|
+
* `Raad.stopped?` will return true
|
87
|
+
|
88
|
+
There are basically 3 ways to run execute your service:
|
89
|
+
|
90
|
+
* start it in foreground console mode, useful for debugging, `^C` to execute the stop sequence
|
91
|
+
|
92
|
+
``` sh
|
93
|
+
$ ruby your_service.rb start
|
94
|
+
```
|
95
|
+
|
96
|
+
* start it as a detached, backgrounded daemon:
|
97
|
+
|
98
|
+
``` sh
|
99
|
+
$ ruby your_service.rb -d start
|
100
|
+
```
|
101
|
+
|
102
|
+
* stop the daemonized service by signaling it to execute the stop sequence
|
103
|
+
|
104
|
+
``` sh
|
105
|
+
$ ruby your_service.rb stop
|
106
|
+
```
|
107
|
+
|
108
|
+
In **console mode** Raad logging for level `:info` and up and stdout, ie `puts`, will be displayed by default.
|
109
|
+
|
110
|
+
In **daemon mode**, Raad logging for level `:info` and up will be output in `your_service.log` log file and the
|
111
|
+
`your_service.pid`pid file will be created.
|
112
|
+
|
113
|
+
To toggle output of all logging levels simply use the verbose `-v` parameter.
|
114
|
+
|
55
115
|
### Supported rubies and environments
|
56
116
|
Raad has been tested on MRI 1.8.7, MRI 1.9.2, REE 1.8.7, JRuby 1.6.4 under OSX 10.6.8 and Linux Ubuntu 10.04
|
57
117
|
|
@@ -87,28 +147,38 @@ tbd.
|
|
87
147
|
tbd.
|
88
148
|
|
89
149
|
### Testing
|
90
|
-
There are specs and a validation suite which ca be run in
|
150
|
+
There are specs and a validation suite which ca be run in your **current** ruby environment:
|
91
151
|
|
92
|
-
|
93
|
-
|
152
|
+
``` sh
|
153
|
+
$ rake spec
|
154
|
+
```
|
155
|
+
``` sh
|
156
|
+
$ rake validation
|
157
|
+
```
|
94
158
|
|
95
|
-
Also, specs and validations can be run in all currently tested Ruby environement
|
159
|
+
Also, specs and validations can be run in **all currently tested Ruby environement**. For this [RVM][rvm] is required and the following rubies must be installed:
|
96
160
|
|
97
161
|
- ruby-1.8.7
|
98
162
|
- ree-1.8.7
|
99
163
|
- ruby-1.9.2
|
100
164
|
- jruby-1.6.4
|
101
165
|
|
102
|
-
In each of these rubies, the gemset @raad containing log4r
|
166
|
+
In each of these rubies, the gemset @raad containing `log4r ~> 1.1.9`, `rake ~> 0.9.2` and `rspec ~> 2.6.0` must be created.
|
103
167
|
|
104
168
|
This RVM environment can be created/updated using:
|
105
169
|
|
106
|
-
|
170
|
+
``` sh
|
171
|
+
$ rake rvm_setup
|
172
|
+
```
|
107
173
|
|
108
174
|
To launch the tests for all rubies use:
|
109
175
|
|
110
|
-
|
111
|
-
|
176
|
+
``` sh
|
177
|
+
$ rake specs
|
178
|
+
```
|
179
|
+
``` sh
|
180
|
+
$ rake validations
|
181
|
+
```
|
112
182
|
|
113
183
|
## TODO
|
114
184
|
- better doc
|
@@ -1,18 +1,16 @@
|
|
1
1
|
module Raad
|
2
2
|
|
3
|
-
# The
|
4
|
-
# handler to run the
|
5
|
-
class
|
3
|
+
# The bootstrap class for Raad. This will execute in the at_exit
|
4
|
+
# handler to run the service.
|
5
|
+
class Bootstrap
|
6
6
|
|
7
|
-
# Set of caller regex's to be skippe when looking for our API file
|
8
7
|
CALLERS_TO_IGNORE = [ # :nodoc:
|
9
|
-
/\/raad(\/(
|
10
|
-
/rubygems\/custom_require\.rb$/,
|
11
|
-
/bundler(\/runtime)?\.rb/,
|
12
|
-
/<internal:/
|
8
|
+
/\/raad(\/(bootstrap))?\.rb$/, # all raad code
|
9
|
+
/rubygems\/custom_require\.rb$/, # rubygems require hacks
|
10
|
+
/bundler(\/runtime)?\.rb/, # bundler require hacks
|
11
|
+
/<internal:/ # internal in ruby >= 1.9.2
|
13
12
|
]
|
14
13
|
|
15
|
-
# @todo add rubinius (and hopefully other VM impls) ignore patterns ...
|
16
14
|
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
|
17
15
|
|
18
16
|
# Like Kernel#caller but excluding certain magic entries and without
|
@@ -21,7 +19,7 @@ module Raad
|
|
21
19
|
caller_locations.map { |file, line| file }
|
22
20
|
end
|
23
21
|
|
24
|
-
#
|
22
|
+
# like caller_files, but containing Arrays rather than strings with the
|
25
23
|
# first element being the file, and the second being the line.
|
26
24
|
def self.caller_locations
|
27
25
|
caller(1).
|
@@ -29,7 +27,7 @@ module Raad
|
|
29
27
|
reject { |file, line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
|
30
28
|
end
|
31
29
|
|
32
|
-
#
|
30
|
+
# find the service_file that was used to execute the service
|
33
31
|
#
|
34
32
|
# @return [String] The service file
|
35
33
|
def self.service_file
|
@@ -38,20 +36,20 @@ module Raad
|
|
38
36
|
c
|
39
37
|
end
|
40
38
|
|
41
|
-
#
|
39
|
+
# execute the service
|
42
40
|
#
|
43
41
|
# @return [Nil]
|
44
42
|
def self.run!
|
45
43
|
file = File.basename(service_file, '.rb')
|
46
44
|
service = Object.module_eval(camel_case(file)).new
|
47
45
|
|
48
|
-
runner =
|
46
|
+
runner = Runner.new(ARGV, service)
|
49
47
|
runner.run
|
50
48
|
end
|
51
49
|
|
52
50
|
private
|
53
51
|
|
54
|
-
#
|
52
|
+
# convert a string to camel case
|
55
53
|
#
|
56
54
|
# @param str [String] The string to convert
|
57
55
|
# @return [String] The camel cased string
|
@@ -63,8 +61,10 @@ module Raad
|
|
63
61
|
end
|
64
62
|
|
65
63
|
at_exit do
|
66
|
-
|
67
|
-
|
64
|
+
unless defined?($RAAD_NOT_RUN)
|
65
|
+
if $!.nil? && $0 == Raad::Bootstrap.service_file
|
66
|
+
Raad::Bootstrap.run!
|
67
|
+
end
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
data/lib/raad/env.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'rbconfig'
|
2
|
+
require 'thread'
|
2
3
|
|
3
4
|
module Raad
|
4
5
|
|
5
6
|
@env = :development
|
7
|
+
@stopped = false
|
8
|
+
@stop_lock = Mutex.new
|
6
9
|
|
7
10
|
# retrieves the current environment
|
8
11
|
#
|
@@ -13,13 +16,14 @@ module Raad
|
|
13
16
|
|
14
17
|
# sets the current environment
|
15
18
|
#
|
16
|
-
# @param [String or Symbol] env the environment
|
19
|
+
# @param [String or Symbol] env the environment
|
17
20
|
def env=(env)
|
18
21
|
case(env.to_s)
|
19
22
|
when 'dev', 'development' then @env = :development
|
20
23
|
when 'prod', 'production' then @env = :production
|
21
24
|
when 'stage', 'staging' then @env = :stage
|
22
25
|
when 'test' then @env = :test
|
26
|
+
else @env = env.to_sym
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
@@ -55,7 +59,7 @@ module Raad
|
|
55
59
|
#
|
56
60
|
# @return [Boolean] true if runnig inside jruby
|
57
61
|
def jruby?
|
58
|
-
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
62
|
+
!!(defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby')
|
59
63
|
end
|
60
64
|
|
61
65
|
# absolute path of current interpreter
|
@@ -65,6 +69,20 @@ module Raad
|
|
65
69
|
File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"] + Config::CONFIG["EXEEXT"])
|
66
70
|
end
|
67
71
|
|
68
|
-
|
72
|
+
# a request to stop the service has been received (or the #start method has returned and, if defined, the service #stop method has been called by Raad.
|
73
|
+
#
|
74
|
+
# @return [Boolean] true is the service has been stopped
|
75
|
+
def stopped?
|
76
|
+
@stop_lock.synchronize{@stopped}
|
77
|
+
end
|
78
|
+
|
79
|
+
# used internally to set the stopped flag
|
80
|
+
#
|
81
|
+
# @param [Boolean] state true to set the stopped flag
|
82
|
+
def stopped=(state)
|
83
|
+
@stop_lock.synchronize{@stopped = !!state}
|
84
|
+
end
|
85
|
+
|
86
|
+
module_function :env, :env=, :production?, :development?, :stage?, :test?, :jruby?, :ruby_path, :stopped?, :stopped=
|
69
87
|
|
70
88
|
end
|
data/lib/raad/runner.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'timeout'
|
3
|
+
require 'thread'
|
2
4
|
|
3
5
|
module Raad
|
4
6
|
class Runner
|
@@ -29,6 +31,7 @@ module Raad
|
|
29
31
|
@logger_options = nil
|
30
32
|
@pid_file = nil
|
31
33
|
|
34
|
+
@stop_lock = Mutex.new
|
32
35
|
@stop_signaled = false
|
33
36
|
end
|
34
37
|
|
@@ -58,8 +61,8 @@ module Raad
|
|
58
61
|
if options[:command] == 'stop'
|
59
62
|
puts(">> Raad service wrapper v#{VERSION} stopping")
|
60
63
|
# first send the TERM signal which will invoke the daemon wait_or_will method which will timeout after @stop_timeout
|
61
|
-
# if still not stopped afer @stop_timeout + 2, KILL -9 will be sent.
|
62
|
-
success = send_signal('TERM', @stop_timeout + 2)
|
64
|
+
# if still not stopped afer @stop_timeout + 2 seconds, KILL -9 will be sent.
|
65
|
+
success = send_signal('TERM', @stop_timeout + (2 * SECOND))
|
63
66
|
exit(success)
|
64
67
|
end
|
65
68
|
|
@@ -92,25 +95,29 @@ module Raad
|
|
92
95
|
end
|
93
96
|
|
94
97
|
# do not trap :QUIT because its not supported in jruby
|
95
|
-
[:INT, :TERM].each
|
96
|
-
SignalTrampoline.trap(sig) {@stop_signaled = true; stop_service}
|
97
|
-
end
|
98
|
+
[:INT, :TERM].each{|sig| SignalTrampoline.trap(sig) {stop_service}}
|
98
99
|
|
99
100
|
# launch the service thread and call start. we expect start not to return
|
100
101
|
# unless it is done or has been stopped.
|
101
102
|
service_thread = Thread.new do
|
102
103
|
Thread.current.abort_on_exception = true
|
103
104
|
service.start
|
104
|
-
stop_service
|
105
|
+
stop_service
|
105
106
|
end
|
106
107
|
|
108
|
+
result = wait_or_kill(service_thread)
|
109
|
+
# if not daemonized start a sentinel thread, if still alive after 2 seconds, do arakiri
|
110
|
+
Thread.new{sleep(2 * SECOND); Process.kill(:KILL, Process.pid)} unless options[:daemonize]
|
107
111
|
# use exit and not exit! to make sure the at_exit hooks are called, like the pid cleanup, etc.
|
108
|
-
exit(
|
112
|
+
exit(result)
|
109
113
|
end
|
110
114
|
|
111
115
|
def stop_service
|
116
|
+
return if @stop_lock.synchronize{s = @stop_signaled; @stop_signaled = true; s}
|
117
|
+
|
112
118
|
Logger.info("stopping #{@service_name} service")
|
113
119
|
service.stop if service.respond_to?(:stop)
|
120
|
+
Raad.stopped = true
|
114
121
|
end
|
115
122
|
|
116
123
|
# try to do a timeout join periodically on the given thread. if the join succeed then the stop
|
@@ -122,7 +129,7 @@ module Raad
|
|
122
129
|
def wait_or_kill(thread)
|
123
130
|
while thread.join(SECOND).nil?
|
124
131
|
# the join has timed out, thread is still buzzy.
|
125
|
-
if @stop_signaled
|
132
|
+
if @stop_lock.synchronize{@stop_signaled}
|
126
133
|
# but if stop has been signalled, start "the final countdown" ♫
|
127
134
|
try = 0; join = nil
|
128
135
|
while (try += 1) <= @stop_timeout && join.nil? do
|
data/lib/raad/unix_daemon.rb
CHANGED
@@ -78,28 +78,22 @@ module Daemonizable
|
|
78
78
|
false
|
79
79
|
end
|
80
80
|
rescue Timeout::Error
|
81
|
-
force_kill_and_remove_pid_file
|
81
|
+
force_kill_and_remove_pid_file(pid)
|
82
82
|
rescue Interrupt
|
83
|
-
force_kill_and_remove_pid_file
|
83
|
+
force_kill_and_remove_pid_file(pid)
|
84
84
|
rescue Errno::ESRCH # No such process
|
85
85
|
puts(">> can't stop process, no such process #{pid}")
|
86
86
|
remove_pid_file
|
87
87
|
false
|
88
88
|
end
|
89
89
|
|
90
|
-
def force_kill_and_remove_pid_file
|
91
|
-
|
92
|
-
|
93
|
-
Process.kill("KILL", pid)
|
94
|
-
true
|
95
|
-
else
|
96
|
-
puts(">> can't stop process, no pid found in #{@pid_file}")
|
97
|
-
false
|
98
|
-
end
|
90
|
+
def force_kill_and_remove_pid_file(pid)
|
91
|
+
puts(">> sending KILL signal to process #{pid}")
|
92
|
+
Process.kill("KILL", pid)
|
99
93
|
remove_pid_file
|
100
|
-
|
94
|
+
true
|
101
95
|
rescue Errno::ESRCH # No such process
|
102
|
-
puts(">> can't
|
96
|
+
puts(">> can't send KILL, no such process #{pid}")
|
103
97
|
remove_pid_file
|
104
98
|
false
|
105
99
|
end
|
data/lib/raad/version.rb
CHANGED
data/lib/raad.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-23 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubyforge
|
16
|
-
requirement: &
|
16
|
+
requirement: &2165092620 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2165092620
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2165092060 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.6.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2165092060
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &2165091540 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.9.2
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2165091540
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: log4r
|
49
|
-
requirement: &
|
49
|
+
requirement: &2165091060 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: 1.1.9
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2165091060
|
58
58
|
description: Ruby as a Daemon lightweight service wrapper
|
59
59
|
email:
|
60
60
|
- colin.surprenant@gmail.com
|
@@ -62,11 +62,11 @@ executables: []
|
|
62
62
|
extensions: []
|
63
63
|
extra_rdoc_files: []
|
64
64
|
files:
|
65
|
+
- lib/raad/bootstrap.rb
|
65
66
|
- lib/raad/configuration.rb
|
66
67
|
- lib/raad/env.rb
|
67
68
|
- lib/raad/logger.rb
|
68
69
|
- lib/raad/runner.rb
|
69
|
-
- lib/raad/service.rb
|
70
70
|
- lib/raad/signal_trampoline.rb
|
71
71
|
- lib/raad/spoon.rb
|
72
72
|
- lib/raad/unix_daemon.rb
|