process-daemon 1.0.0 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/lib/process/daemon/controller.rb +7 -2
- data/lib/process/daemon/listen.rb +85 -0
- data/lib/process/daemon/version.rb +1 -1
- data/spec/process/daemon/process_file_spec.rb +0 -4
- data/spec/process/daemon/terminate_spec.rb +71 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c61cccea3d2c60a71ac3a57248e041a6474d1fc8
|
4
|
+
data.tar.gz: 547c4355486f24c30eeb00c4aed3c633d0290656
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c984adf509aa62ba982fccb52dea7f692b44b9300a38f79d4ce4c8225185e66b113ad723634aea8084a749cb8900ed3e3b30c567b381113dc1167e1adcc4af21
|
7
|
+
data.tar.gz: 195aff6013ab3a1b61d7865cf8292caafa05e797a1f01b9d8d4db8fdb4b0735d92d7f067217e70a0c79f2e194fcb9fe71b4959fafd84ba6d477f00867d16fe73
|
data/README.md
CHANGED
@@ -32,11 +32,12 @@ A process daemon has a specific structure:
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def run
|
35
|
-
# Do the actual work. Does not need to be implemented, e.g. if using threads or other background processing mechanisms.
|
35
|
+
# Do the actual work. Does not need to be implemented, e.g. if using threads or other background processing mechanisms which were kicked off in #startup.
|
36
36
|
end
|
37
37
|
|
38
38
|
def shutdown
|
39
|
-
# Stop everything that was setup in startup.
|
39
|
+
# Stop everything that was setup in startup. Called as part of main daemon thread/process, not in trap context (e.g. SIGINT).
|
40
|
+
# Asynchronous code can call self.request_shutdown from a trap context to interrupt the main process, provided you aren't doing work in #run.
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -57,6 +58,8 @@ After calling `prefork`, the working directory is expanded to a full path and sh
|
|
57
58
|
|
58
59
|
### WEBRick Server
|
59
60
|
|
61
|
+
Some servers must run on the main process thread. In this case, the normal interrupt mechanism won't be used and we will handle signals directly.
|
62
|
+
|
60
63
|
Create a file for your daemon, e.g. `daemon.rb`:
|
61
64
|
|
62
65
|
#!/usr/bin/env ruby
|
@@ -188,8 +188,12 @@ module Process
|
|
188
188
|
end
|
189
189
|
|
190
190
|
pgid = -Process.getpgid(pid)
|
191
|
-
|
191
|
+
|
192
|
+
# Stop by interrupt sends a single interrupt and waits for the process to terminate:
|
192
193
|
unless stop_by_interrupt(pgid)
|
194
|
+
# If the process is still running, we try sending SIGTERM followed by SIGKILL:
|
195
|
+
@output.puts Rainbow("** Daemon did not stop gracefully after #{@stop_timeout}s **").red
|
196
|
+
|
193
197
|
stop_by_terminate_or_kill(pgid)
|
194
198
|
end
|
195
199
|
|
@@ -207,6 +211,7 @@ module Process
|
|
207
211
|
|
208
212
|
private
|
209
213
|
|
214
|
+
# Returns true if the process was stopped.
|
210
215
|
def stop_by_interrupt(pgid)
|
211
216
|
running = true
|
212
217
|
|
@@ -219,7 +224,7 @@ module Process
|
|
219
224
|
end
|
220
225
|
end
|
221
226
|
|
222
|
-
return running
|
227
|
+
return !running
|
223
228
|
end
|
224
229
|
|
225
230
|
def stop_by_terminate_or_kill(pgid)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Process
|
22
|
+
class Daemon
|
23
|
+
# Access incoming file descriptors from daemons started by systemd.
|
24
|
+
class Listen
|
25
|
+
LISTEN_PID = 'LISTEN_PID'
|
26
|
+
LISTEN_FDS = 'LISTEN_FDS'
|
27
|
+
LISTEN_FDNAMES = 'LISTEN_FDNAMES'
|
28
|
+
|
29
|
+
FD_START = 3
|
30
|
+
SEPERATOR = ':'
|
31
|
+
|
32
|
+
def self.set_close_at_exec(fd)
|
33
|
+
fd.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.open(fd)
|
37
|
+
set_close_at_exec(fd)
|
38
|
+
|
39
|
+
return IO.for_fd(fd)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a Array or Hash of file descriptors. If LISTEN_FDNAMES is set, a Hash is returned which includes key => value pairs for named file descriptors.
|
43
|
+
def self.file_descriptors(env = ENV)
|
44
|
+
pid, fds, names = env.values_at(LISTEN_PID, LISTEN_FDS, LISTEN_FDNAMES)
|
45
|
+
|
46
|
+
# Are the PIDs valid for this process?
|
47
|
+
unless pid and Integer(pid) == Process.pid
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
|
51
|
+
files = Integer(fds).times.collect do |i|
|
52
|
+
self.open(FD_START + i)
|
53
|
+
end
|
54
|
+
|
55
|
+
if names
|
56
|
+
names = names.split(SEPARATOR, -1)
|
57
|
+
end
|
58
|
+
|
59
|
+
self.new(files, names)
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(files, names)
|
63
|
+
@files = files
|
64
|
+
@names = names
|
65
|
+
|
66
|
+
@named = {}
|
67
|
+
@unnamed = []
|
68
|
+
|
69
|
+
@names.each_with_index do |name, index|
|
70
|
+
if name
|
71
|
+
@named[name] = @files[index]
|
72
|
+
else
|
73
|
+
@unnamed << @files[index]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
attr :files
|
79
|
+
attr :names
|
80
|
+
|
81
|
+
attr :named
|
82
|
+
attr :unnamed
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'process/daemon'
|
22
|
+
require 'process/daemon/process_file'
|
23
|
+
|
24
|
+
module Process::Daemon::TerminateSpec
|
25
|
+
class SleepDaemon < Process::Daemon
|
26
|
+
def working_directory
|
27
|
+
File.expand_path("../tmp", __FILE__)
|
28
|
+
end
|
29
|
+
|
30
|
+
def startup
|
31
|
+
setup_signals
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_signals
|
35
|
+
trap('INT') do
|
36
|
+
puts 'INT'
|
37
|
+
end
|
38
|
+
|
39
|
+
trap('TERM') do
|
40
|
+
puts 'TERM'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
sleep 1 while true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe Process::Daemon do
|
50
|
+
let(:daemon) {SleepDaemon.instance}
|
51
|
+
let(:controller) {Process::Daemon::Controller.new(daemon)}
|
52
|
+
|
53
|
+
# Print out the daemon log file:
|
54
|
+
#after(:each) do
|
55
|
+
# system('cat', daemon.log_file_path)
|
56
|
+
#end
|
57
|
+
|
58
|
+
it "should be killed" do
|
59
|
+
controller.start
|
60
|
+
|
61
|
+
expect(controller.status).to be == :running
|
62
|
+
|
63
|
+
controller.stop
|
64
|
+
|
65
|
+
expect(controller.status).to be == :stopped
|
66
|
+
|
67
|
+
output = File.readlines(daemon.log_file_path).last(6)
|
68
|
+
expect(output).to be == ["INT\n", "TERM\n", "TERM\n", "TERM\n", "TERM\n", "TERM\n"]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process-daemon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rainbow
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- lib/process/daemon.rb
|
84
84
|
- lib/process/daemon/controller.rb
|
85
|
+
- lib/process/daemon/listen.rb
|
85
86
|
- lib/process/daemon/log_file.rb
|
86
87
|
- lib/process/daemon/notification.rb
|
87
88
|
- lib/process/daemon/privileges.rb
|
@@ -96,6 +97,7 @@ files:
|
|
96
97
|
- spec/process/daemon/notification_spec.rb
|
97
98
|
- spec/process/daemon/privileges_spec.rb
|
98
99
|
- spec/process/daemon/process_file_spec.rb
|
100
|
+
- spec/process/daemon/terminate_spec.rb
|
99
101
|
homepage: https://github.com/ioquatix/process-daemon
|
100
102
|
licenses:
|
101
103
|
- MIT
|
@@ -130,3 +132,4 @@ test_files:
|
|
130
132
|
- spec/process/daemon/notification_spec.rb
|
131
133
|
- spec/process/daemon/privileges_spec.rb
|
132
134
|
- spec/process/daemon/process_file_spec.rb
|
135
|
+
- spec/process/daemon/terminate_spec.rb
|