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 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 shudown gracefully before receiving a SIGKILL, defaults to 5."
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.
@@ -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
- trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
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 processesstarted by this +Engine+
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 killall(signal="SIGTERM")
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
- killall "SIGKILL"
420
+ kill_children "SIGKILL"
312
421
  else
313
422
  system "sending SIGTERM to all processes"
314
- killall "SIGTERM"
423
+ kill_children "SIGTERM"
315
424
  end
316
425
  Timeout.timeout(options[:timeout]) do
317
426
  watch_for_termination while @running.length > 0
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.61.0"
3
+ VERSION = "0.62.0"
4
4
 
5
5
  end
@@ -41,7 +41,7 @@ describe Foreman::Process do
41
41
 
42
42
  it "should output utf8 properly" do
43
43
  process = Foreman::Process.new(resource_path("bin/utf8"))
44
- run(process).should == "\xFF\x03\n"
44
+ run(process).should == "\xFF\x03\n".force_encoding('binary')
45
45
  end
46
46
  end
47
47
 
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.61.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-01-14 00:00:00.000000000 Z
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: &70171274222360 !ruby/object:Gem::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: *70171274222360
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: &70171274248800 !ruby/object:Gem::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: *70171274248800
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: 1.8.11
150
+ rubygems_version: 2.0.0
147
151
  signing_key:
148
- specification_version: 3
152
+ specification_version: 4
149
153
  summary: Process manager for applications with multiple components
150
154
  test_files: []
151
155
  has_rdoc: