puma 5.0.4 → 5.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +250 -48
- data/README.md +90 -24
- data/docs/architecture.md +57 -20
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +53 -67
- data/docs/fork_worker.md +2 -0
- data/docs/jungle/rc.d/README.md +1 -1
- data/docs/kubernetes.md +66 -0
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +7 -7
- data/docs/signals.md +10 -10
- data/docs/stats.md +142 -0
- data/docs/systemd.md +85 -66
- data/ext/puma_http11/extconf.rb +36 -6
- data/ext/puma_http11/http11_parser.c +64 -59
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +1 -1
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +177 -84
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +39 -41
- data/ext/puma_http11/puma_http11.c +8 -2
- data/lib/puma/app/status.rb +4 -7
- data/lib/puma/binder.rb +121 -46
- data/lib/puma/cli.rb +9 -0
- data/lib/puma/client.rb +58 -19
- data/lib/puma/cluster/worker.rb +19 -16
- data/lib/puma/cluster/worker_handle.rb +9 -2
- data/lib/puma/cluster.rb +46 -22
- data/lib/puma/configuration.rb +18 -2
- data/lib/puma/const.rb +14 -4
- data/lib/puma/control_cli.rb +76 -71
- data/lib/puma/detect.rb +14 -10
- data/lib/puma/dsl.rb +143 -26
- data/lib/puma/error_logger.rb +12 -5
- data/lib/puma/events.rb +18 -3
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +54 -6
- data/lib/puma/minissl/context_builder.rb +6 -0
- data/lib/puma/minissl.rb +54 -38
- data/lib/puma/null_io.rb +12 -0
- data/lib/puma/plugin.rb +1 -1
- data/lib/puma/queue_close.rb +7 -7
- data/lib/puma/rack/builder.rb +1 -1
- data/lib/puma/reactor.rb +19 -12
- data/lib/puma/request.rb +45 -16
- data/lib/puma/runner.rb +38 -13
- data/lib/puma/server.rb +62 -123
- data/lib/puma/state_file.rb +5 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +10 -7
- data/lib/puma/util.rb +8 -1
- data/lib/puma.rb +36 -10
- data/lib/rack/handler/puma.rb +1 -0
- metadata +15 -9
data/lib/puma/cluster.rb
CHANGED
@@ -43,6 +43,7 @@ module Puma
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def start_phased_restart
|
46
|
+
@events.fire_on_restart!
|
46
47
|
@phase += 1
|
47
48
|
log "- Starting phased worker restart, phase: #{@phase}"
|
48
49
|
|
@@ -114,7 +115,7 @@ module Puma
|
|
114
115
|
debug "Workers to cull: #{workers_to_cull.inspect}"
|
115
116
|
|
116
117
|
workers_to_cull.each do |worker|
|
117
|
-
log "- Worker #{worker.index} (
|
118
|
+
log "- Worker #{worker.index} (PID: #{worker.pid}) terminating"
|
118
119
|
worker.term
|
119
120
|
end
|
120
121
|
end
|
@@ -163,16 +164,6 @@ module Puma
|
|
163
164
|
].compact.min
|
164
165
|
end
|
165
166
|
|
166
|
-
def wakeup!
|
167
|
-
return unless @wakeup
|
168
|
-
|
169
|
-
begin
|
170
|
-
@wakeup.write "!" unless @wakeup.closed?
|
171
|
-
rescue SystemCallError, IOError
|
172
|
-
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
167
|
def worker(index, master)
|
177
168
|
@workers = []
|
178
169
|
|
@@ -317,7 +308,7 @@ module Puma
|
|
317
308
|
|
318
309
|
stop_workers
|
319
310
|
stop
|
320
|
-
|
311
|
+
@events.fire_on_stopped!
|
321
312
|
raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
|
322
313
|
exit 0 # Clean exit, workers were stopped
|
323
314
|
end
|
@@ -329,15 +320,25 @@ module Puma
|
|
329
320
|
|
330
321
|
output_header "cluster"
|
331
322
|
|
332
|
-
|
333
|
-
|
334
|
-
before = Thread.list
|
323
|
+
# This is aligned with the output from Runner, see Runner#output_header
|
324
|
+
log "* Workers: #{@options[:workers]}"
|
335
325
|
|
336
326
|
if preload?
|
327
|
+
# Threads explicitly marked as fork safe will be ignored. Used in Rails,
|
328
|
+
# but may be used by anyone. Note that we need to explicit
|
329
|
+
# Process::Waiter check here because there's a bug in Ruby 2.6 and below
|
330
|
+
# where calling thread_variable_get on a Process::Waiter will segfault.
|
331
|
+
# We can drop that clause once those versions of Ruby are no longer
|
332
|
+
# supported.
|
333
|
+
fork_safe = ->(t) { !t.is_a?(Process::Waiter) && t.thread_variable_get(:fork_safe) }
|
334
|
+
|
335
|
+
before = Thread.list.reject(&fork_safe)
|
336
|
+
|
337
|
+
log "* Restarts: (\u2714) hot (\u2716) phased"
|
337
338
|
log "* Preloading application"
|
338
339
|
load_and_bind
|
339
340
|
|
340
|
-
after = Thread.list
|
341
|
+
after = Thread.list.reject(&fork_safe)
|
341
342
|
|
342
343
|
if after.size > before.size
|
343
344
|
threads = (after - before)
|
@@ -351,7 +352,7 @@ module Puma
|
|
351
352
|
end
|
352
353
|
end
|
353
354
|
else
|
354
|
-
log "*
|
355
|
+
log "* Restarts: (\u2714) hot (\u2714) phased"
|
355
356
|
|
356
357
|
unless @launcher.config.app_configured?
|
357
358
|
error "No application configured, nothing to run"
|
@@ -378,6 +379,8 @@ module Puma
|
|
378
379
|
|
379
380
|
log "Use Ctrl-C to stop"
|
380
381
|
|
382
|
+
single_worker_warning
|
383
|
+
|
381
384
|
redirect_io
|
382
385
|
|
383
386
|
Plugins.fire_background
|
@@ -399,19 +402,21 @@ module Puma
|
|
399
402
|
|
400
403
|
begin
|
401
404
|
booted = false
|
405
|
+
in_phased_restart = false
|
406
|
+
workers_not_booted = @options[:workers]
|
402
407
|
|
403
408
|
while @status == :run
|
404
409
|
begin
|
405
410
|
if @phased_restart
|
406
411
|
start_phased_restart
|
407
412
|
@phased_restart = false
|
413
|
+
in_phased_restart = true
|
414
|
+
workers_not_booted = @options[:workers]
|
408
415
|
end
|
409
416
|
|
410
417
|
check_workers
|
411
418
|
|
412
|
-
|
413
|
-
|
414
|
-
if res
|
419
|
+
if read.wait_readable([0, @next_check - Time.now].max)
|
415
420
|
req = read.read_nonblock(1)
|
416
421
|
|
417
422
|
@next_check = Time.now if req == "!"
|
@@ -430,8 +435,9 @@ module Puma
|
|
430
435
|
case req
|
431
436
|
when "b"
|
432
437
|
w.boot!
|
433
|
-
log "- Worker #{w.index} (
|
438
|
+
log "- Worker #{w.index} (PID: #{pid}) booted in #{w.uptime.round(2)}s, phase: #{w.phase}"
|
434
439
|
@next_check = Time.now
|
440
|
+
workers_not_booted -= 1
|
435
441
|
when "e"
|
436
442
|
# external term, see worker method, Signal.trap "SIGTERM"
|
437
443
|
w.instance_variable_set :@term, true
|
@@ -449,6 +455,10 @@ module Puma
|
|
449
455
|
log "! Out-of-sync worker list, no #{pid} worker"
|
450
456
|
end
|
451
457
|
end
|
458
|
+
if in_phased_restart && workers_not_booted.zero?
|
459
|
+
@events.fire_on_booted!
|
460
|
+
in_phased_restart = false
|
461
|
+
end
|
452
462
|
|
453
463
|
rescue Interrupt
|
454
464
|
@status = :stop
|
@@ -466,6 +476,15 @@ module Puma
|
|
466
476
|
|
467
477
|
private
|
468
478
|
|
479
|
+
def single_worker_warning
|
480
|
+
return if @options[:workers] != 1 || @options[:silence_single_worker_warning]
|
481
|
+
|
482
|
+
log "! WARNING: Detected running cluster mode with 1 worker."
|
483
|
+
log "! Running Puma in cluster mode with a single worker is often a misconfiguration."
|
484
|
+
log "! Consider running Puma in single-mode (workers = 0) in order to reduce memory overhead."
|
485
|
+
log "! Set the `silence_single_worker_warning` option to silence this warning message."
|
486
|
+
end
|
487
|
+
|
469
488
|
# loops thru @workers, removing workers that exited, and calling
|
470
489
|
# `#term` if needed
|
471
490
|
def wait_workers
|
@@ -495,7 +514,12 @@ module Puma
|
|
495
514
|
def timeout_workers
|
496
515
|
@workers.each do |w|
|
497
516
|
if !w.term? && w.ping_timeout <= Time.now
|
498
|
-
|
517
|
+
details = if w.booted?
|
518
|
+
"(worker failed to check in within #{@options[:worker_timeout]} seconds)"
|
519
|
+
else
|
520
|
+
"(worker failed to boot within #{@options[:worker_boot_timeout]} seconds)"
|
521
|
+
end
|
522
|
+
log "! Terminating timed out worker #{details}: #{w.pid}"
|
499
523
|
w.kill
|
500
524
|
end
|
501
525
|
end
|
data/lib/puma/configuration.rb
CHANGED
@@ -92,6 +92,12 @@ module Puma
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
95
|
+
|
96
|
+
def final_options
|
97
|
+
default_options
|
98
|
+
.merge(file_options)
|
99
|
+
.merge(user_options)
|
100
|
+
end
|
95
101
|
end
|
96
102
|
|
97
103
|
# The main configuration class of Puma.
|
@@ -187,18 +193,22 @@ module Puma
|
|
187
193
|
:debug => false,
|
188
194
|
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
189
195
|
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
196
|
+
:silence_single_worker_warning => false,
|
190
197
|
:mode => :http,
|
191
198
|
:worker_timeout => DefaultWorkerTimeout,
|
192
199
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
193
200
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
194
201
|
:remote_address => :socket,
|
195
202
|
:tag => method(:infer_tag),
|
196
|
-
:environment => -> { ENV['RACK_ENV'] || ENV['RAILS_ENV'] ||
|
203
|
+
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
197
204
|
:rackup => DefaultRackup,
|
198
205
|
:logger => STDOUT,
|
199
206
|
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
200
207
|
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
201
|
-
:raise_exception_on_sigterm => true
|
208
|
+
:raise_exception_on_sigterm => true,
|
209
|
+
:max_fast_inline => Const::MAX_FAST_INLINE,
|
210
|
+
:io_selector_backend => :auto,
|
211
|
+
:mutate_stdout_and_stderr_to_sync_on_write => true,
|
202
212
|
}
|
203
213
|
end
|
204
214
|
|
@@ -289,6 +299,10 @@ module Puma
|
|
289
299
|
end
|
290
300
|
end
|
291
301
|
|
302
|
+
def final_options
|
303
|
+
@options.final_options
|
304
|
+
end
|
305
|
+
|
292
306
|
def self.temp_path
|
293
307
|
require 'tmpdir'
|
294
308
|
|
@@ -329,6 +343,8 @@ module Puma
|
|
329
343
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
330
344
|
|
331
345
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
346
|
+
rack_options = rack_options || {}
|
347
|
+
|
332
348
|
@options.file_options.merge!(rack_options)
|
333
349
|
|
334
350
|
config_ru_binds = []
|
data/lib/puma/const.rb
CHANGED
@@ -100,8 +100,8 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "5.
|
104
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "5.5.1".freeze
|
104
|
+
CODE_NAME = "Zawgyi".freeze
|
105
105
|
|
106
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
107
107
|
|
@@ -228,7 +228,6 @@ module Puma
|
|
228
228
|
COLON = ": ".freeze
|
229
229
|
|
230
230
|
NEWLINE = "\n".freeze
|
231
|
-
HTTP_INJECTION_REGEX = /[\r\n]/.freeze
|
232
231
|
|
233
232
|
HIJACK_P = "rack.hijack?".freeze
|
234
233
|
HIJACK = "rack.hijack".freeze
|
@@ -236,8 +235,19 @@ module Puma
|
|
236
235
|
|
237
236
|
EARLY_HINTS = "rack.early_hints".freeze
|
238
237
|
|
239
|
-
#
|
238
|
+
# Minimum interval to checks worker health
|
240
239
|
WORKER_CHECK_INTERVAL = 5
|
241
240
|
|
241
|
+
# Illegal character in the key or value of response header
|
242
|
+
DQUOTE = "\"".freeze
|
243
|
+
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
244
|
+
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
245
|
+
# header values can contain HTAB?
|
246
|
+
ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
|
247
|
+
|
248
|
+
# Banned keys of response header
|
249
|
+
BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
|
250
|
+
|
251
|
+
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
242
252
|
end
|
243
253
|
end
|
data/lib/puma/control_cli.rb
CHANGED
@@ -11,10 +11,32 @@ require 'socket'
|
|
11
11
|
module Puma
|
12
12
|
class ControlCLI
|
13
13
|
|
14
|
-
|
14
|
+
# values must be string or nil
|
15
|
+
# value of `nil` means command cannot be processed via signal
|
16
|
+
# @version 5.0.3
|
17
|
+
CMD_PATH_SIG_MAP = {
|
18
|
+
'gc' => nil,
|
19
|
+
'gc-stats' => nil,
|
20
|
+
'halt' => 'SIGQUIT',
|
21
|
+
'phased-restart' => 'SIGUSR1',
|
22
|
+
'refork' => 'SIGURG',
|
23
|
+
'reload-worker-directory' => nil,
|
24
|
+
'restart' => 'SIGUSR2',
|
25
|
+
'start' => nil,
|
26
|
+
'stats' => nil,
|
27
|
+
'status' => '',
|
28
|
+
'stop' => 'SIGTERM',
|
29
|
+
'thread-backtraces' => nil
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
# @deprecated 6.0.0
|
33
|
+
COMMANDS = CMD_PATH_SIG_MAP.keys.freeze
|
34
|
+
|
35
|
+
# commands that cannot be used in a request
|
36
|
+
NO_REQ_COMMANDS = %w{refork}.freeze
|
15
37
|
|
16
38
|
# @version 5.0.0
|
17
|
-
PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}
|
39
|
+
PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}.freeze
|
18
40
|
|
19
41
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
20
42
|
@state = nil
|
@@ -25,7 +47,7 @@ module Puma
|
|
25
47
|
@control_auth_token = nil
|
26
48
|
@config_file = nil
|
27
49
|
@command = nil
|
28
|
-
@environment = ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
50
|
+
@environment = ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
29
51
|
|
30
52
|
@argv = argv.dup
|
31
53
|
@stdout = stdout
|
@@ -33,7 +55,7 @@ module Puma
|
|
33
55
|
@cli_options = {}
|
34
56
|
|
35
57
|
opts = OptionParser.new do |o|
|
36
|
-
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{
|
58
|
+
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{CMD_PATH_SIG_MAP.keys.join("|")})"
|
37
59
|
|
38
60
|
o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
|
39
61
|
@state = arg
|
@@ -74,7 +96,7 @@ module Puma
|
|
74
96
|
end
|
75
97
|
|
76
98
|
o.on_tail("-V", "--version", "Show version") do
|
77
|
-
puts Const::PUMA_VERSION
|
99
|
+
@stdout.puts Const::PUMA_VERSION
|
78
100
|
exit
|
79
101
|
end
|
80
102
|
end
|
@@ -86,10 +108,10 @@ module Puma
|
|
86
108
|
|
87
109
|
# check presence of command
|
88
110
|
unless @command
|
89
|
-
raise "Available commands: #{
|
111
|
+
raise "Available commands: #{CMD_PATH_SIG_MAP.keys.join(", ")}"
|
90
112
|
end
|
91
113
|
|
92
|
-
unless
|
114
|
+
unless CMD_PATH_SIG_MAP.key? @command
|
93
115
|
raise "Invalid command: #{@command}"
|
94
116
|
end
|
95
117
|
|
@@ -134,7 +156,7 @@ module Puma
|
|
134
156
|
@pid = sf.pid
|
135
157
|
elsif @pidfile
|
136
158
|
# get pid from pid_file
|
137
|
-
File.
|
159
|
+
@pid = File.read(@pidfile, mode: 'rb:UTF-8').to_i
|
138
160
|
end
|
139
161
|
end
|
140
162
|
|
@@ -142,24 +164,29 @@ module Puma
|
|
142
164
|
uri = URI.parse @control_url
|
143
165
|
|
144
166
|
# create server object by scheme
|
145
|
-
server =
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
167
|
+
server =
|
168
|
+
case uri.scheme
|
169
|
+
when 'ssl'
|
170
|
+
require 'openssl'
|
171
|
+
OpenSSL::SSL::SSLSocket.new(
|
172
|
+
TCPSocket.new(uri.host, uri.port),
|
173
|
+
OpenSSL::SSL::SSLContext.new)
|
174
|
+
.tap { |ssl| ssl.sync_close = true } # default is false
|
175
|
+
.tap(&:connect)
|
176
|
+
when 'tcp'
|
177
|
+
TCPSocket.new uri.host, uri.port
|
178
|
+
when 'unix'
|
179
|
+
# check for abstract UNIXSocket
|
180
|
+
UNIXSocket.new(@control_url.start_with?('unix://@') ?
|
181
|
+
"\0#{uri.host}#{uri.path}" : "#{uri.host}#{uri.path}")
|
182
|
+
else
|
183
|
+
raise "Invalid scheme: #{uri.scheme}"
|
184
|
+
end
|
185
|
+
|
186
|
+
if @command == 'status'
|
187
|
+
message 'Puma is started'
|
188
|
+
elsif NO_REQ_COMMANDS.include? @command
|
189
|
+
raise "Invalid request command: #{@command}"
|
163
190
|
else
|
164
191
|
url = "/#{@command}"
|
165
192
|
|
@@ -167,10 +194,10 @@ module Puma
|
|
167
194
|
url = url + "?token=#{@control_auth_token}"
|
168
195
|
end
|
169
196
|
|
170
|
-
server
|
197
|
+
server.syswrite "GET #{url} HTTP/1.0\r\n\r\n"
|
171
198
|
|
172
199
|
unless data = server.read
|
173
|
-
raise
|
200
|
+
raise 'Server closed connection before responding'
|
174
201
|
end
|
175
202
|
|
176
203
|
response = data.split("\r\n")
|
@@ -179,13 +206,13 @@ module Puma
|
|
179
206
|
raise "Server sent empty response"
|
180
207
|
end
|
181
208
|
|
182
|
-
|
209
|
+
@http, @code, @message = response.first.split(' ',3)
|
183
210
|
|
184
|
-
if @code ==
|
185
|
-
raise
|
186
|
-
elsif @code ==
|
211
|
+
if @code == '403'
|
212
|
+
raise 'Unauthorized access to server (wrong auth token)'
|
213
|
+
elsif @code == '404'
|
187
214
|
raise "Command error: #{response.last}"
|
188
|
-
elsif @code !=
|
215
|
+
elsif @code != '200'
|
189
216
|
raise "Bad response from server: #{@code}"
|
190
217
|
end
|
191
218
|
|
@@ -194,7 +221,7 @@ module Puma
|
|
194
221
|
end
|
195
222
|
ensure
|
196
223
|
if server
|
197
|
-
if uri.scheme ==
|
224
|
+
if uri.scheme == 'ssl'
|
198
225
|
server.sysclose
|
199
226
|
else
|
200
227
|
server.close unless server.closed?
|
@@ -204,51 +231,30 @@ module Puma
|
|
204
231
|
|
205
232
|
def send_signal
|
206
233
|
unless @pid
|
207
|
-
raise
|
234
|
+
raise 'Neither pid nor control url available'
|
208
235
|
end
|
209
236
|
|
210
237
|
begin
|
238
|
+
sig = CMD_PATH_SIG_MAP[@command]
|
211
239
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
when "halt"
|
217
|
-
Process.kill "QUIT", @pid
|
218
|
-
|
219
|
-
when "stop"
|
220
|
-
Process.kill "SIGTERM", @pid
|
221
|
-
|
222
|
-
when "stats"
|
223
|
-
puts "Stats not available via pid only"
|
224
|
-
return
|
225
|
-
|
226
|
-
when "reload-worker-directory"
|
227
|
-
puts "reload-worker-directory not available via pid only"
|
240
|
+
if sig.nil?
|
241
|
+
@stdout.puts "'#{@command}' not available via pid only"
|
242
|
+
@stdout.flush unless @stdout.sync
|
228
243
|
return
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
when "status"
|
244
|
+
elsif sig.start_with? 'SIG'
|
245
|
+
Process.kill sig, @pid
|
246
|
+
elsif @command == 'status'
|
234
247
|
begin
|
235
248
|
Process.kill 0, @pid
|
236
|
-
puts
|
249
|
+
@stdout.puts 'Puma is started'
|
250
|
+
@stdout.flush unless @stdout.sync
|
237
251
|
rescue Errno::ESRCH
|
238
|
-
raise
|
252
|
+
raise 'Puma is not running'
|
239
253
|
end
|
240
|
-
|
241
|
-
return
|
242
|
-
|
243
|
-
when "refork"
|
244
|
-
Process.kill "SIGURG", @pid
|
245
|
-
|
246
|
-
else
|
247
254
|
return
|
248
255
|
end
|
249
|
-
|
250
256
|
rescue SystemCallError
|
251
|
-
if @command ==
|
257
|
+
if @command == 'restart'
|
252
258
|
start
|
253
259
|
else
|
254
260
|
raise "No pid '#{@pid}' found"
|
@@ -259,14 +265,13 @@ module Puma
|
|
259
265
|
end
|
260
266
|
|
261
267
|
def run
|
262
|
-
return start if @command ==
|
263
|
-
|
268
|
+
return start if @command == 'start'
|
264
269
|
prepare_configuration
|
265
270
|
|
266
|
-
if Puma.windows?
|
271
|
+
if Puma.windows? || @control_url
|
267
272
|
send_request
|
268
273
|
else
|
269
|
-
|
274
|
+
send_signal
|
270
275
|
end
|
271
276
|
|
272
277
|
rescue => e
|
data/lib/puma/detect.rb
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# This file can be loaded independently of puma.rb, so it cannot have any code
|
4
|
+
# that assumes puma.rb is loaded.
|
5
|
+
|
6
|
+
|
3
7
|
module Puma
|
4
|
-
#
|
5
|
-
|
8
|
+
# @version 5.2.1
|
9
|
+
HAS_FORK = ::Process.respond_to? :fork
|
6
10
|
|
7
|
-
|
8
|
-
HAS_SSL
|
9
|
-
end
|
11
|
+
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
10
12
|
|
11
|
-
|
13
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/ ||
|
14
|
+
IS_JRUBY && RUBY_DESCRIPTION =~ /mswin/)
|
15
|
+
|
16
|
+
# @version 5.2.0
|
17
|
+
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
12
18
|
|
13
19
|
def self.jruby?
|
14
20
|
IS_JRUBY
|
15
21
|
end
|
16
22
|
|
17
|
-
IS_WINDOWS = RUBY_PLATFORM =~ /mswin|ming|cygwin/
|
18
|
-
|
19
23
|
def self.windows?
|
20
24
|
IS_WINDOWS
|
21
25
|
end
|
22
26
|
|
23
27
|
# @version 5.0.0
|
24
28
|
def self.mri?
|
25
|
-
|
29
|
+
IS_MRI
|
26
30
|
end
|
27
31
|
|
28
32
|
# @version 5.0.0
|
29
33
|
def self.forkable?
|
30
|
-
|
34
|
+
HAS_FORK
|
31
35
|
end
|
32
36
|
end
|