foreman 0.61.0-java → 0.62.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4bceec3667a30e0e2f03405297ca261a18777b9e
4
+ data.tar.gz: 7f1c9dd62f6ac00d05db018b7ba05bdb792d5fe5
5
+ SHA512:
6
+ metadata.gz: 67dc455b1e317bdf2d917734a0d9a653ef9cbe4a7392ff533b918f070d0563fb3c2fa427165e56a827de1de83271f2d45f254e2ae7c3bbf4514638f359024508
7
+ data.tar.gz: 9b8953d964c21f3372ad757dc865cca897bd8cd762a5ae1e81b3348a58b2a7da54dab4b3dba341a2b30e1697c8bec22d9361055ac167714fb7c78b1dd11f976a
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: java
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: &70341187029940 !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: *70341187029940
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: posix-spawn
27
- requirement: &70341187029340 !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: 0.3.6
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *70341187029340
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.6
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: