puma 4.3.12 → 5.6.6
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 +1511 -524
- data/LICENSE +23 -20
- data/README.md +120 -36
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +60 -69
- data/docs/fork_worker.md +33 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +46 -23
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +85 -128
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +44 -10
- data/ext/puma_http11/http11_parser.c +45 -47
- 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 +0 -0
- data/ext/puma_http11/mini_ssl.c +225 -89
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +3 -5
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
- data/ext/puma_http11/puma_http11.c +32 -51
- data/lib/puma/app/status.rb +50 -36
- data/lib/puma/binder.rb +225 -106
- data/lib/puma/cli.rb +24 -18
- data/lib/puma/client.rb +104 -76
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +212 -220
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -49
- data/lib/puma/const.rb +13 -6
- data/lib/puma/control_cli.rb +99 -76
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +368 -96
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -34
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +128 -46
- data/lib/puma/minissl/context_builder.rb +14 -9
- data/lib/puma/minissl.rb +137 -50
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +1 -5
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +0 -0
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +476 -0
- data/lib/puma/runner.rb +46 -61
- data/lib/puma/server.rb +292 -763
- data/lib/puma/single.rb +9 -65
- data/lib/puma/state_file.rb +48 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +125 -57
- data/lib/puma/util.rb +32 -4
- data/lib/puma.rb +48 -0
- data/lib/rack/handler/puma.rb +2 -3
- data/lib/rack/version_restriction.rb +15 -0
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +28 -23
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/accept_nonblock.rb +0 -29
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/configuration.rb
CHANGED
@@ -11,6 +11,7 @@ module Puma
|
|
11
11
|
|
12
12
|
DefaultTCPHost = "0.0.0.0"
|
13
13
|
DefaultTCPPort = 9292
|
14
|
+
DefaultWorkerCheckInterval = 5
|
14
15
|
DefaultWorkerTimeout = 60
|
15
16
|
DefaultWorkerShutdownTimeout = 30
|
16
17
|
end
|
@@ -54,9 +55,7 @@ module Puma
|
|
54
55
|
attr_reader :user_options, :file_options, :default_options
|
55
56
|
|
56
57
|
def [](key)
|
57
|
-
|
58
|
-
return file_options[key] if file_options.key?(key)
|
59
|
-
return default_options[key] if default_options.key?(key)
|
58
|
+
fetch(key)
|
60
59
|
end
|
61
60
|
|
62
61
|
def []=(key, value)
|
@@ -64,7 +63,11 @@ module Puma
|
|
64
63
|
end
|
65
64
|
|
66
65
|
def fetch(key, default_value = nil)
|
67
|
-
|
66
|
+
return user_options[key] if user_options.key?(key)
|
67
|
+
return file_options[key] if file_options.key?(key)
|
68
|
+
return default_options[key] if default_options.key?(key)
|
69
|
+
|
70
|
+
default_value
|
68
71
|
end
|
69
72
|
|
70
73
|
def all_of(key)
|
@@ -90,6 +93,12 @@ module Puma
|
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
96
|
+
|
97
|
+
def final_options
|
98
|
+
default_options
|
99
|
+
.merge(file_options)
|
100
|
+
.merge(user_options)
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
# The main configuration class of Puma.
|
@@ -106,16 +115,17 @@ module Puma
|
|
106
115
|
#
|
107
116
|
# It also handles loading plugins.
|
108
117
|
#
|
109
|
-
#
|
118
|
+
# [Note:]
|
119
|
+
# `:port` and `:host` are not valid keys. By the time they make it to the
|
110
120
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
111
121
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
112
122
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
123
|
+
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
124
|
+
# user_config.port 3003
|
125
|
+
# end
|
126
|
+
# config.load
|
127
|
+
# puts config.options[:port]
|
128
|
+
# # => 3003
|
119
129
|
#
|
120
130
|
# It is expected that `load` is called on the configuration instance after setting
|
121
131
|
# config. This method expands any values in `config_file` and puts them into the
|
@@ -137,6 +147,10 @@ module Puma
|
|
137
147
|
@file_dsl = DSL.new(@options.file_options, self)
|
138
148
|
@default_dsl = DSL.new(@options.default_options, self)
|
139
149
|
|
150
|
+
if !@options[:prune_bundler]
|
151
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
152
|
+
end
|
153
|
+
|
140
154
|
if block
|
141
155
|
configure(&block)
|
142
156
|
end
|
@@ -167,27 +181,37 @@ module Puma
|
|
167
181
|
self
|
168
182
|
end
|
169
183
|
|
184
|
+
# @version 5.0.0
|
185
|
+
def default_max_threads
|
186
|
+
Puma.mri? ? 5 : 16
|
187
|
+
end
|
188
|
+
|
170
189
|
def puma_default_options
|
171
190
|
{
|
172
|
-
:min_threads => 0,
|
173
|
-
:max_threads =>
|
191
|
+
:min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
|
192
|
+
:max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
|
174
193
|
:log_requests => false,
|
175
194
|
:debug => false,
|
176
195
|
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
177
|
-
:workers => 0,
|
178
|
-
:
|
196
|
+
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
197
|
+
:silence_single_worker_warning => false,
|
179
198
|
:mode => :http,
|
199
|
+
:worker_check_interval => DefaultWorkerCheckInterval,
|
180
200
|
:worker_timeout => DefaultWorkerTimeout,
|
181
201
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
182
202
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
203
|
+
:worker_culling_strategy => :youngest,
|
183
204
|
:remote_address => :socket,
|
184
205
|
:tag => method(:infer_tag),
|
185
|
-
:environment => -> { ENV['RACK_ENV'] ||
|
206
|
+
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
186
207
|
:rackup => DefaultRackup,
|
187
208
|
:logger => STDOUT,
|
188
209
|
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
189
210
|
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
190
|
-
:raise_exception_on_sigterm => true
|
211
|
+
:raise_exception_on_sigterm => true,
|
212
|
+
:max_fast_inline => Const::MAX_FAST_INLINE,
|
213
|
+
:io_selector_backend => :auto,
|
214
|
+
:mutate_stdout_and_stderr_to_sync_on_write => true,
|
191
215
|
}
|
192
216
|
end
|
193
217
|
|
@@ -245,14 +269,6 @@ module Puma
|
|
245
269
|
def app
|
246
270
|
found = options[:app] || load_rackup
|
247
271
|
|
248
|
-
if @options[:mode] == :tcp
|
249
|
-
require 'puma/tcp_logger'
|
250
|
-
|
251
|
-
logger = @options[:logger]
|
252
|
-
quiet = !@options[:log_requests]
|
253
|
-
return TCPLogger.new(logger, found, quiet)
|
254
|
-
end
|
255
|
-
|
256
272
|
if @options[:log_requests]
|
257
273
|
require 'puma/commonlogger'
|
258
274
|
logger = @options[:logger]
|
@@ -275,8 +291,19 @@ module Puma
|
|
275
291
|
@plugins.create name
|
276
292
|
end
|
277
293
|
|
278
|
-
def run_hooks(key, arg)
|
279
|
-
@options.all_of(key).each
|
294
|
+
def run_hooks(key, arg, events)
|
295
|
+
@options.all_of(key).each do |b|
|
296
|
+
begin
|
297
|
+
b.call arg
|
298
|
+
rescue => e
|
299
|
+
events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
300
|
+
events.debug e.backtrace.join("\n")
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def final_options
|
306
|
+
@options.final_options
|
280
307
|
end
|
281
308
|
|
282
309
|
def self.temp_path
|
@@ -319,6 +346,8 @@ module Puma
|
|
319
346
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
320
347
|
|
321
348
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
349
|
+
rack_options = rack_options || {}
|
350
|
+
|
322
351
|
@options.file_options.merge!(rack_options)
|
323
352
|
|
324
353
|
config_ru_binds = []
|
@@ -332,29 +361,9 @@ module Puma
|
|
332
361
|
end
|
333
362
|
|
334
363
|
def self.random_token
|
335
|
-
|
336
|
-
require 'openssl'
|
337
|
-
rescue LoadError
|
338
|
-
end
|
339
|
-
|
340
|
-
count = 16
|
341
|
-
|
342
|
-
bytes = nil
|
343
|
-
|
344
|
-
if defined? OpenSSL::Random
|
345
|
-
bytes = OpenSSL::Random.random_bytes(count)
|
346
|
-
elsif File.exist?("/dev/urandom")
|
347
|
-
File.open('/dev/urandom') { |f| bytes = f.read(count) }
|
348
|
-
end
|
349
|
-
|
350
|
-
if bytes
|
351
|
-
token = "".dup
|
352
|
-
bytes.each_byte { |b| token << b.to_s(16) }
|
353
|
-
else
|
354
|
-
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
355
|
-
end
|
364
|
+
require 'securerandom' unless defined?(SecureRandom)
|
356
365
|
|
357
|
-
|
366
|
+
SecureRandom.hex(16)
|
358
367
|
end
|
359
368
|
end
|
360
369
|
end
|
data/lib/puma/const.rb
CHANGED
@@ -100,8 +100,9 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "
|
104
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "5.6.6".freeze
|
104
|
+
CODE_NAME = "Birdie's Version".freeze
|
105
|
+
|
105
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
107
|
|
107
108
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
@@ -177,7 +178,6 @@ module Puma
|
|
177
178
|
PORT_443 = "443".freeze
|
178
179
|
LOCALHOST = "localhost".freeze
|
179
180
|
LOCALHOST_IP = "127.0.0.1".freeze
|
180
|
-
LOCALHOST_ADDR = "127.0.0.1:0".freeze
|
181
181
|
|
182
182
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
183
183
|
HTTP_11 = "HTTP/1.1".freeze
|
@@ -230,7 +230,6 @@ module Puma
|
|
230
230
|
COLON = ": ".freeze
|
231
231
|
|
232
232
|
NEWLINE = "\n".freeze
|
233
|
-
HTTP_INJECTION_REGEX = /[\r\n]/.freeze
|
234
233
|
|
235
234
|
HIJACK_P = "rack.hijack?".freeze
|
236
235
|
HIJACK = "rack.hijack".freeze
|
@@ -238,8 +237,16 @@ module Puma
|
|
238
237
|
|
239
238
|
EARLY_HINTS = "rack.early_hints".freeze
|
240
239
|
|
241
|
-
#
|
242
|
-
|
240
|
+
# Illegal character in the key or value of response header
|
241
|
+
DQUOTE = "\"".freeze
|
242
|
+
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
243
|
+
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
244
|
+
# header values can contain HTAB?
|
245
|
+
ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
|
246
|
+
|
247
|
+
# Banned keys of response header
|
248
|
+
BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
|
243
249
|
|
250
|
+
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
244
251
|
end
|
245
252
|
end
|
data/lib/puma/control_cli.rb
CHANGED
@@ -11,7 +11,36 @@ 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
|
+
'info' => 'SIGINFO',
|
22
|
+
'phased-restart' => 'SIGUSR1',
|
23
|
+
'refork' => 'SIGURG',
|
24
|
+
'reload-worker-directory' => nil,
|
25
|
+
'reopen-log' => 'SIGHUP',
|
26
|
+
'restart' => 'SIGUSR2',
|
27
|
+
'start' => nil,
|
28
|
+
'stats' => nil,
|
29
|
+
'status' => '',
|
30
|
+
'stop' => 'SIGTERM',
|
31
|
+
'thread-backtraces' => nil,
|
32
|
+
'worker-count-down' => 'SIGTTOU',
|
33
|
+
'worker-count-up' => 'SIGTTIN'
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
# @deprecated 6.0.0
|
37
|
+
COMMANDS = CMD_PATH_SIG_MAP.keys.freeze
|
38
|
+
|
39
|
+
# commands that cannot be used in a request
|
40
|
+
NO_REQ_COMMANDS = %w[info reopen-log worker-count-down worker-count-up].freeze
|
41
|
+
|
42
|
+
# @version 5.0.0
|
43
|
+
PRINTABLE_COMMANDS = %w[gc-stats stats thread-backtraces].freeze
|
15
44
|
|
16
45
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
17
46
|
@state = nil
|
@@ -22,7 +51,7 @@ module Puma
|
|
22
51
|
@control_auth_token = nil
|
23
52
|
@config_file = nil
|
24
53
|
@command = nil
|
25
|
-
@environment = ENV['RACK_ENV']
|
54
|
+
@environment = ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
26
55
|
|
27
56
|
@argv = argv.dup
|
28
57
|
@stdout = stdout
|
@@ -30,7 +59,7 @@ module Puma
|
|
30
59
|
@cli_options = {}
|
31
60
|
|
32
61
|
opts = OptionParser.new do |o|
|
33
|
-
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{
|
62
|
+
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{CMD_PATH_SIG_MAP.keys.join("|")})"
|
34
63
|
|
35
64
|
o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
|
36
65
|
@state = arg
|
@@ -71,7 +100,7 @@ module Puma
|
|
71
100
|
end
|
72
101
|
|
73
102
|
o.on_tail("-V", "--version", "Show version") do
|
74
|
-
puts Const::PUMA_VERSION
|
103
|
+
@stdout.puts Const::PUMA_VERSION
|
75
104
|
exit
|
76
105
|
end
|
77
106
|
end
|
@@ -81,6 +110,15 @@ module Puma
|
|
81
110
|
|
82
111
|
@command = argv.shift
|
83
112
|
|
113
|
+
# check presence of command
|
114
|
+
unless @command
|
115
|
+
raise "Available commands: #{CMD_PATH_SIG_MAP.keys.join(", ")}"
|
116
|
+
end
|
117
|
+
|
118
|
+
unless CMD_PATH_SIG_MAP.key? @command
|
119
|
+
raise "Invalid command: #{@command}"
|
120
|
+
end
|
121
|
+
|
84
122
|
unless @config_file == '-'
|
85
123
|
environment = @environment || 'development'
|
86
124
|
|
@@ -99,16 +137,6 @@ module Puma
|
|
99
137
|
@pidfile ||= config.options[:pidfile]
|
100
138
|
end
|
101
139
|
end
|
102
|
-
|
103
|
-
# check present of command
|
104
|
-
unless @command
|
105
|
-
raise "Available commands: #{COMMANDS.join(", ")}"
|
106
|
-
end
|
107
|
-
|
108
|
-
unless COMMANDS.include? @command
|
109
|
-
raise "Invalid command: #{@command}"
|
110
|
-
end
|
111
|
-
|
112
140
|
rescue => e
|
113
141
|
@stdout.puts e.message
|
114
142
|
exit 1
|
@@ -132,7 +160,7 @@ module Puma
|
|
132
160
|
@pid = sf.pid
|
133
161
|
elsif @pidfile
|
134
162
|
# get pid from pid_file
|
135
|
-
File.
|
163
|
+
@pid = File.read(@pidfile, mode: 'rb:UTF-8').to_i
|
136
164
|
end
|
137
165
|
end
|
138
166
|
|
@@ -140,23 +168,27 @@ module Puma
|
|
140
168
|
uri = URI.parse @control_url
|
141
169
|
|
142
170
|
# create server object by scheme
|
143
|
-
server =
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
171
|
+
server =
|
172
|
+
case uri.scheme
|
173
|
+
when 'ssl'
|
174
|
+
require 'openssl'
|
175
|
+
OpenSSL::SSL::SSLSocket.new(
|
176
|
+
TCPSocket.new(uri.host, uri.port),
|
177
|
+
OpenSSL::SSL::SSLContext.new)
|
178
|
+
.tap { |ssl| ssl.sync_close = true } # default is false
|
179
|
+
.tap(&:connect)
|
180
|
+
when 'tcp'
|
181
|
+
TCPSocket.new uri.host, uri.port
|
182
|
+
when 'unix'
|
183
|
+
# check for abstract UNIXSocket
|
184
|
+
UNIXSocket.new(@control_url.start_with?('unix://@') ?
|
185
|
+
"\0#{uri.host}#{uri.path}" : "#{uri.host}#{uri.path}")
|
186
|
+
else
|
187
|
+
raise "Invalid scheme: #{uri.scheme}"
|
188
|
+
end
|
189
|
+
|
190
|
+
if @command == 'status'
|
191
|
+
message 'Puma is started'
|
160
192
|
else
|
161
193
|
url = "/#{@command}"
|
162
194
|
|
@@ -164,10 +196,10 @@ module Puma
|
|
164
196
|
url = url + "?token=#{@control_auth_token}"
|
165
197
|
end
|
166
198
|
|
167
|
-
server
|
199
|
+
server.syswrite "GET #{url} HTTP/1.0\r\n\r\n"
|
168
200
|
|
169
201
|
unless data = server.read
|
170
|
-
raise
|
202
|
+
raise 'Server closed connection before responding'
|
171
203
|
end
|
172
204
|
|
173
205
|
response = data.split("\r\n")
|
@@ -176,67 +208,59 @@ module Puma
|
|
176
208
|
raise "Server sent empty response"
|
177
209
|
end
|
178
210
|
|
179
|
-
|
211
|
+
@http, @code, @message = response.first.split(' ',3)
|
180
212
|
|
181
|
-
if @code ==
|
182
|
-
raise
|
183
|
-
elsif @code ==
|
213
|
+
if @code == '403'
|
214
|
+
raise 'Unauthorized access to server (wrong auth token)'
|
215
|
+
elsif @code == '404'
|
184
216
|
raise "Command error: #{response.last}"
|
185
|
-
elsif @code !=
|
217
|
+
elsif @code != '200'
|
186
218
|
raise "Bad response from server: #{@code}"
|
187
219
|
end
|
188
220
|
|
189
221
|
message "Command #{@command} sent success"
|
190
|
-
message response.last if @command
|
222
|
+
message response.last if PRINTABLE_COMMANDS.include?(@command)
|
191
223
|
end
|
192
224
|
ensure
|
193
|
-
|
225
|
+
if server
|
226
|
+
if uri.scheme == 'ssl'
|
227
|
+
server.sysclose
|
228
|
+
else
|
229
|
+
server.close unless server.closed?
|
230
|
+
end
|
231
|
+
end
|
194
232
|
end
|
195
233
|
|
196
234
|
def send_signal
|
197
235
|
unless @pid
|
198
|
-
raise
|
236
|
+
raise 'Neither pid nor control url available'
|
199
237
|
end
|
200
238
|
|
201
239
|
begin
|
240
|
+
sig = CMD_PATH_SIG_MAP[@command]
|
202
241
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
when "halt"
|
208
|
-
Process.kill "QUIT", @pid
|
209
|
-
|
210
|
-
when "stop"
|
211
|
-
Process.kill "SIGTERM", @pid
|
212
|
-
|
213
|
-
when "stats"
|
214
|
-
puts "Stats not available via pid only"
|
215
|
-
return
|
216
|
-
|
217
|
-
when "reload-worker-directory"
|
218
|
-
puts "reload-worker-directory not available via pid only"
|
242
|
+
if sig.nil?
|
243
|
+
@stdout.puts "'#{@command}' not available via pid only"
|
244
|
+
@stdout.flush unless @stdout.sync
|
219
245
|
return
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
246
|
+
elsif sig.start_with? 'SIG'
|
247
|
+
if Signal.list.key? sig.sub(/\ASIG/, '')
|
248
|
+
Process.kill sig, @pid
|
249
|
+
else
|
250
|
+
raise "Signal '#{sig}' not available'"
|
251
|
+
end
|
252
|
+
elsif @command == 'status'
|
225
253
|
begin
|
226
254
|
Process.kill 0, @pid
|
227
|
-
puts
|
255
|
+
@stdout.puts 'Puma is started'
|
256
|
+
@stdout.flush unless @stdout.sync
|
228
257
|
rescue Errno::ESRCH
|
229
|
-
raise
|
258
|
+
raise 'Puma is not running'
|
230
259
|
end
|
231
|
-
|
232
|
-
return
|
233
|
-
|
234
|
-
else
|
235
260
|
return
|
236
261
|
end
|
237
|
-
|
238
262
|
rescue SystemCallError
|
239
|
-
if @command ==
|
263
|
+
if @command == 'restart'
|
240
264
|
start
|
241
265
|
else
|
242
266
|
raise "No pid '#{@pid}' found"
|
@@ -247,14 +271,13 @@ module Puma
|
|
247
271
|
end
|
248
272
|
|
249
273
|
def run
|
250
|
-
return start if @command ==
|
251
|
-
|
274
|
+
return start if @command == 'start'
|
252
275
|
prepare_configuration
|
253
276
|
|
254
|
-
if Puma.windows?
|
277
|
+
if Puma.windows? || @control_url && !NO_REQ_COMMANDS.include?(@command)
|
255
278
|
send_request
|
256
279
|
else
|
257
|
-
|
280
|
+
send_signal
|
258
281
|
end
|
259
282
|
|
260
283
|
rescue => e
|
@@ -262,7 +285,7 @@ module Puma
|
|
262
285
|
exit 1
|
263
286
|
end
|
264
287
|
|
265
|
-
|
288
|
+
private
|
266
289
|
def start
|
267
290
|
require 'puma/cli'
|
268
291
|
|
data/lib/puma/detect.rb
CHANGED
@@ -1,15 +1,42 @@
|
|
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
|
-
|
8
|
+
# @version 5.2.1
|
9
|
+
HAS_FORK = ::Process.respond_to? :fork
|
10
|
+
|
11
|
+
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
12
|
+
|
13
|
+
IS_OSX = RUBY_PLATFORM.include? 'darwin'
|
14
|
+
|
15
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
|
16
|
+
IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
|
17
|
+
|
18
|
+
# @version 5.2.0
|
19
|
+
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
5
20
|
|
6
21
|
def self.jruby?
|
7
22
|
IS_JRUBY
|
8
23
|
end
|
9
24
|
|
10
|
-
|
25
|
+
def self.osx?
|
26
|
+
IS_OSX
|
27
|
+
end
|
11
28
|
|
12
29
|
def self.windows?
|
13
30
|
IS_WINDOWS
|
14
31
|
end
|
32
|
+
|
33
|
+
# @version 5.0.0
|
34
|
+
def self.mri?
|
35
|
+
IS_MRI
|
36
|
+
end
|
37
|
+
|
38
|
+
# @version 5.0.0
|
39
|
+
def self.forkable?
|
40
|
+
HAS_FORK
|
41
|
+
end
|
15
42
|
end
|