foreman 0.61.0-mingw32 → 0.62.0-mingw32
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 +7 -0
- data/lib/foreman/cli.rb +1 -1
- data/lib/foreman/engine.rb +118 -9
- data/lib/foreman/version.rb +1 -1
- data/spec/foreman/process_spec.rb +1 -1
- metadata +20 -16
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c0a87ff21f4fd9a2caff939e6278a5eb7b94b8f4
|
4
|
+
data.tar.gz: 8cdb734c00c58f7489def4e3a32ffe73851e0f3f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 61805b66d6b87b66015eb064764d26db7c14fd121fd9aaf427dfabb0c0b8e664949da04a3dd3aead077aa2afd25eb778c5d927daf3a56ea7e262aa8a69302aad
|
7
|
+
data.tar.gz: 52a3a51a00a937d8bbfafd246257fc5de2db3773a4671213738a527458d6632b5a99d75d2bd54f3925e38e39d720a9361f9e1cff0a3010492aed1a72737e21cf
|
data/lib/foreman/cli.rb
CHANGED
@@ -23,7 +23,7 @@ class Foreman::CLI < Thor
|
|
23
23
|
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
24
24
|
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
|
25
25
|
method_option :port, :type => :numeric, :aliases => "-p"
|
26
|
-
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to
|
26
|
+
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shutdown gracefully before receiving a SIGKILL, defaults to 5."
|
27
27
|
|
28
28
|
class << self
|
29
29
|
# Hackery. Take the run method away from Thor so that we can redefine it.
|
data/lib/foreman/engine.rb
CHANGED
@@ -9,6 +9,10 @@ require "thread"
|
|
9
9
|
|
10
10
|
class Foreman::Engine
|
11
11
|
|
12
|
+
# The signals that the engine cares about.
|
13
|
+
#
|
14
|
+
HANDLED_SIGNALS = [ :TERM, :INT, :HUP ]
|
15
|
+
|
12
16
|
attr_reader :env
|
13
17
|
attr_reader :options
|
14
18
|
attr_reader :processes
|
@@ -33,6 +37,16 @@ class Foreman::Engine
|
|
33
37
|
@processes = []
|
34
38
|
@running = {}
|
35
39
|
@readers = {}
|
40
|
+
|
41
|
+
# Self-pipe for deferred signal-handling (ala djb: http://cr.yp.to/docs/selfpipe.html)
|
42
|
+
reader, writer = create_pipe
|
43
|
+
reader.close_on_exec = true if reader.respond_to?(:close_on_exec)
|
44
|
+
writer.close_on_exec = true if writer.respond_to?(:close_on_exec)
|
45
|
+
@selfpipe = { :reader => reader, :writer => writer }
|
46
|
+
|
47
|
+
# Set up a global signal queue
|
48
|
+
# http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html
|
49
|
+
Thread.main[:signal_queue] = []
|
36
50
|
end
|
37
51
|
|
38
52
|
# Start the processes registered to this +Engine+
|
@@ -41,10 +55,7 @@ class Foreman::Engine
|
|
41
55
|
# Make sure foreman is the process group leader.
|
42
56
|
Process.setpgrp unless Foreman.windows?
|
43
57
|
|
44
|
-
|
45
|
-
trap("INT") { puts "SIGINT received"; terminate_gracefully }
|
46
|
-
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP'
|
47
|
-
|
58
|
+
register_signal_handlers
|
48
59
|
startup
|
49
60
|
spawn_processes
|
50
61
|
watch_for_output
|
@@ -53,6 +64,74 @@ class Foreman::Engine
|
|
53
64
|
shutdown
|
54
65
|
end
|
55
66
|
|
67
|
+
# Set up deferred signal handlers
|
68
|
+
#
|
69
|
+
def register_signal_handlers
|
70
|
+
HANDLED_SIGNALS.each do |sig|
|
71
|
+
if ::Signal.list.include? sig.to_s
|
72
|
+
trap(sig) { Thread.main[:signal_queue] << sig ; notice_signal }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Unregister deferred signal handlers
|
78
|
+
#
|
79
|
+
def restore_default_signal_handlers
|
80
|
+
HANDLED_SIGNALS.each do |sig|
|
81
|
+
trap(sig, :DEFAULT) if ::Signal.list.include? sig.to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Wake the main thread up via the selfpipe when there's a signal
|
86
|
+
#
|
87
|
+
def notice_signal
|
88
|
+
@selfpipe[:writer].write_nonblock( '.' )
|
89
|
+
rescue Errno::EAGAIN
|
90
|
+
# Ignore writes that would block
|
91
|
+
rescue Errno::EINT
|
92
|
+
# Retry if another signal arrived while writing
|
93
|
+
retry
|
94
|
+
end
|
95
|
+
|
96
|
+
# Invoke the real handler for signal +sig+. This shouldn't be called directly
|
97
|
+
# by signal handlers, as it might invoke code which isn't re-entrant.
|
98
|
+
#
|
99
|
+
# @param [Symbol] sig the name of the signal to be handled
|
100
|
+
#
|
101
|
+
def handle_signal(sig)
|
102
|
+
case sig
|
103
|
+
when :TERM
|
104
|
+
handle_term_signal
|
105
|
+
when :INT
|
106
|
+
handle_interrupt
|
107
|
+
when :HUP
|
108
|
+
handle_hangup
|
109
|
+
else
|
110
|
+
system "unhandled signal #{sig}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Handle a TERM signal
|
115
|
+
#
|
116
|
+
def handle_term_signal
|
117
|
+
puts "SIGTERM received"
|
118
|
+
terminate_gracefully
|
119
|
+
end
|
120
|
+
|
121
|
+
# Handle an INT signal
|
122
|
+
#
|
123
|
+
def handle_interrupt
|
124
|
+
puts "SIGINT received"
|
125
|
+
terminate_gracefully
|
126
|
+
end
|
127
|
+
|
128
|
+
# Handle a HUP signal
|
129
|
+
#
|
130
|
+
def handle_hangup
|
131
|
+
puts "SIGHUP received"
|
132
|
+
terminate_gracefully
|
133
|
+
end
|
134
|
+
|
56
135
|
# Register a process to be run by this +Engine+
|
57
136
|
#
|
58
137
|
# @param [String] name A name for this process
|
@@ -98,11 +177,11 @@ class Foreman::Engine
|
|
98
177
|
end
|
99
178
|
end
|
100
179
|
|
101
|
-
# Send a signal to all
|
180
|
+
# Send a signal to all processes started by this +Engine+
|
102
181
|
#
|
103
182
|
# @param [String] signal The signal to send to each process
|
104
183
|
#
|
105
|
-
def
|
184
|
+
def kill_children(signal="SIGTERM")
|
106
185
|
if Foreman.windows?
|
107
186
|
@running.each do |pid, (process, index)|
|
108
187
|
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
@@ -111,6 +190,21 @@ class Foreman::Engine
|
|
111
190
|
rescue Errno::ESRCH, Errno::EPERM
|
112
191
|
end
|
113
192
|
end
|
193
|
+
else
|
194
|
+
begin
|
195
|
+
Process.kill signal, *@running.keys unless @running.empty?
|
196
|
+
rescue Errno::ESRCH, Errno::EPERM
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Send a signal to the whole process group.
|
202
|
+
#
|
203
|
+
# @param [String] signal The signal to send
|
204
|
+
#
|
205
|
+
def killall(signal="SIGTERM")
|
206
|
+
if Foreman.windows?
|
207
|
+
kill_children(signal)
|
114
208
|
else
|
115
209
|
begin
|
116
210
|
Process.kill "-#{signal}", Process.getpgrp
|
@@ -277,8 +371,22 @@ private
|
|
277
371
|
Thread.new do
|
278
372
|
begin
|
279
373
|
loop do
|
280
|
-
io = IO.select(@readers.values, nil, nil, 30)
|
374
|
+
io = IO.select([@selfpipe[:reader]] + @readers.values, nil, nil, 30)
|
375
|
+
|
376
|
+
begin
|
377
|
+
@selfpipe[:reader].read_nonblock(11)
|
378
|
+
rescue Errno::EAGAIN, Errno::EINTR => err
|
379
|
+
# ignore
|
380
|
+
end
|
381
|
+
|
382
|
+
# Look for any signals that arrived and handle them
|
383
|
+
while sig = Thread.main[:signal_queue].shift
|
384
|
+
self.handle_signal(sig)
|
385
|
+
end
|
386
|
+
|
281
387
|
(io.nil? ? [] : io.first).each do |reader|
|
388
|
+
next if reader == @selfpipe[:reader]
|
389
|
+
|
282
390
|
if reader.eof?
|
283
391
|
@readers.delete_if { |key, value| value == reader }
|
284
392
|
else
|
@@ -305,13 +413,14 @@ private
|
|
305
413
|
|
306
414
|
def terminate_gracefully
|
307
415
|
return if @terminating
|
416
|
+
restore_default_signal_handlers
|
308
417
|
@terminating = true
|
309
418
|
if Foreman.windows?
|
310
419
|
system "sending SIGKILL to all processes"
|
311
|
-
|
420
|
+
kill_children "SIGKILL"
|
312
421
|
else
|
313
422
|
system "sending SIGTERM to all processes"
|
314
|
-
|
423
|
+
kill_children "SIGTERM"
|
315
424
|
end
|
316
425
|
Timeout.timeout(options[:timeout]) do
|
317
426
|
watch_for_termination while @running.length > 0
|
data/lib/foreman/version.rb
CHANGED
metadata
CHANGED
@@ -1,38 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.62.0
|
6
5
|
platform: mingw32
|
7
6
|
authors:
|
8
7
|
- David Dollar
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-03-08 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: thor
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.13.6
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.13.6
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: win32console
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - ~>
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: 1.3.0
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.3.0
|
36
41
|
description: Process manager for applications with multiple components
|
37
42
|
email: ddollar@gmail.com
|
38
43
|
executables:
|
@@ -125,27 +130,26 @@ files:
|
|
125
130
|
homepage: http://github.com/ddollar/foreman
|
126
131
|
licenses:
|
127
132
|
- MIT
|
133
|
+
metadata: {}
|
128
134
|
post_install_message:
|
129
135
|
rdoc_options: []
|
130
136
|
require_paths:
|
131
137
|
- lib
|
132
138
|
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
-
none: false
|
134
139
|
requirements:
|
135
|
-
- -
|
140
|
+
- - '>='
|
136
141
|
- !ruby/object:Gem::Version
|
137
142
|
version: '0'
|
138
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
-
none: false
|
140
144
|
requirements:
|
141
|
-
- -
|
145
|
+
- - '>='
|
142
146
|
- !ruby/object:Gem::Version
|
143
147
|
version: '0'
|
144
148
|
requirements: []
|
145
149
|
rubyforge_project:
|
146
|
-
rubygems_version:
|
150
|
+
rubygems_version: 2.0.0
|
147
151
|
signing_key:
|
148
|
-
specification_version:
|
152
|
+
specification_version: 4
|
149
153
|
summary: Process manager for applications with multiple components
|
150
154
|
test_files: []
|
151
155
|
has_rdoc:
|