puma 2.2.0 → 8.0.2
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/History.md +3334 -0
- data/LICENSE +23 -20
- data/README.md +387 -100
- data/bin/puma-wild +25 -0
- data/bin/pumactl +1 -1
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/architecture.md +74 -0
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +137 -0
- data/docs/fork_worker.md +41 -0
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -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/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/java_options.md +54 -0
- data/docs/jungle/README.md +9 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/docs/kubernetes.md +73 -0
- data/docs/nginx.md +5 -5
- data/docs/plugins.md +42 -0
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +65 -0
- data/docs/signals.md +98 -0
- data/docs/stats.md +148 -0
- data/docs/systemd.md +253 -0
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/extconf.rb +59 -2
- data/ext/puma_http11/http11_parser.c +319 -487
- data/ext/puma_http11/http11_parser.h +15 -13
- data/ext/puma_http11/http11_parser.java.rl +64 -94
- data/ext/puma_http11/http11_parser.rl +27 -24
- data/ext/puma_http11/http11_parser_common.rl +8 -8
- data/ext/puma_http11/mini_ssl.c +696 -38
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +241 -145
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +174 -221
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +413 -193
- data/ext/puma_http11/puma_http11.c +183 -175
- data/lib/puma/app/status.rb +77 -29
- data/lib/puma/binder.rb +349 -119
- data/lib/puma/cli.rb +163 -801
- data/lib/puma/client.rb +627 -144
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +127 -0
- data/lib/puma/cluster.rb +634 -0
- data/lib/puma/cluster_accept_loop_delay.rb +91 -0
- data/lib/puma/commonlogger.rb +115 -0
- data/lib/puma/configuration.rb +420 -198
- data/lib/puma/const.rb +266 -115
- data/lib/puma/control_cli.rb +219 -120
- data/lib/puma/detect.rb +56 -2
- data/lib/puma/dsl.rb +1562 -0
- data/lib/puma/error_logger.rb +115 -0
- data/lib/puma/events.rb +44 -60
- data/lib/puma/io_buffer.rb +48 -5
- data/lib/puma/jruby_restart.rb +2 -51
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +102 -0
- data/lib/puma/launcher.rb +501 -0
- data/lib/puma/log_writer.rb +153 -0
- data/lib/puma/minissl/context_builder.rb +96 -0
- data/lib/puma/minissl.rb +355 -37
- data/lib/puma/null_io.rb +79 -12
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +36 -0
- data/lib/puma/plugin.rb +111 -0
- data/lib/puma/rack/builder.rb +297 -0
- data/lib/puma/rack/urlmap.rb +93 -0
- data/lib/puma/rack_default.rb +21 -4
- data/lib/puma/reactor.rb +102 -133
- data/lib/puma/response.rb +532 -0
- data/lib/puma/runner.rb +211 -0
- data/lib/puma/sd_notify.rb +146 -0
- data/lib/puma/server.rb +582 -445
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/single.rb +72 -0
- data/lib/puma/state_file.rb +69 -0
- data/lib/puma/thread_pool.rb +389 -57
- data/lib/puma/util.rb +125 -0
- data/lib/puma.rb +80 -6
- data/lib/rack/handler/puma.rb +125 -47
- data/tools/Dockerfile +26 -0
- data/tools/trickletest.rb +44 -0
- metadata +88 -148
- data/COPYING +0 -55
- data/Gemfile +0 -10
- data/History.txt +0 -302
- data/Manifest.txt +0 -60
- data/Rakefile +0 -165
- data/TODO +0 -5
- data/docs/config.md +0 -0
- data/ext/puma_http11/ext_help.h +0 -15
- data/ext/puma_http11/io_buffer.c +0 -154
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/capistrano.rb +0 -34
- data/lib/puma/compat.rb +0 -11
- data/lib/puma/daemon_ext.rb +0 -20
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack_patch.rb +0 -25
- data/puma.gemspec +0 -45
- data/test/test_app_status.rb +0 -88
- data/test/test_cli.rb +0 -171
- data/test/test_config.rb +0 -16
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -126
- data/test/test_integration.rb +0 -154
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -25
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -224
- data/test/test_rack_handler.rb +0 -10
- data/test/test_rack_server.rb +0 -141
- data/test/test_thread_pool.rb +0 -146
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
- data/tools/jungle/init.d/README.md +0 -54
- data/tools/jungle/init.d/puma +0 -332
- data/tools/jungle/init.d/run-puma +0 -3
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -52
data/lib/puma/cli.rb
CHANGED
|
@@ -1,883 +1,245 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'optparse'
|
|
2
4
|
require 'uri'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
require 'puma/daemon_ext'
|
|
10
|
-
require 'puma/util'
|
|
11
|
-
|
|
12
|
-
require 'rack/commonlogger'
|
|
13
|
-
require 'rack/utils'
|
|
6
|
+
require_relative '../puma'
|
|
7
|
+
require_relative 'configuration'
|
|
8
|
+
require_relative 'launcher'
|
|
9
|
+
require_relative 'const'
|
|
10
|
+
require_relative 'log_writer'
|
|
14
11
|
|
|
15
12
|
module Puma
|
|
13
|
+
class << self
|
|
14
|
+
# The CLI exports a Puma::Configuration instance here to allow
|
|
15
|
+
# apps to pick it up. An app must load this object conditionally
|
|
16
|
+
# because it is not set if the app is launched via any mechanism
|
|
17
|
+
# other than the CLI class.
|
|
18
|
+
attr_accessor :cli_config
|
|
19
|
+
end
|
|
20
|
+
|
|
16
21
|
# Handles invoke a Puma::Server in a command line style.
|
|
17
22
|
#
|
|
18
23
|
class CLI
|
|
19
24
|
# Create a new CLI object using +argv+ as the command line
|
|
20
25
|
# arguments.
|
|
21
26
|
#
|
|
22
|
-
|
|
23
|
-
# this object will report status on.
|
|
24
|
-
#
|
|
25
|
-
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
|
27
|
+
def initialize(argv, log_writer = LogWriter.stdio, events = Events.new, env: ENV)
|
|
26
28
|
@debug = false
|
|
27
|
-
@argv = argv
|
|
28
|
-
@
|
|
29
|
-
@
|
|
30
|
-
|
|
31
|
-
@phase = 0
|
|
32
|
-
@workers = []
|
|
33
|
-
|
|
34
|
-
@events = Events.new @stdout, @stderr
|
|
35
|
-
|
|
36
|
-
@server = nil
|
|
37
|
-
@status = nil
|
|
38
|
-
|
|
39
|
-
@restart = false
|
|
40
|
-
@phased_state = :idle
|
|
41
|
-
|
|
42
|
-
@app = nil
|
|
43
|
-
|
|
44
|
-
ENV['NEWRELIC_DISPATCHER'] ||= "puma"
|
|
45
|
-
|
|
46
|
-
setup_options
|
|
47
|
-
|
|
48
|
-
generate_restart_data
|
|
49
|
-
|
|
50
|
-
@binder = Binder.new(@events)
|
|
51
|
-
@binder.import_from_env
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def restart_on_stop!
|
|
55
|
-
@restart = true
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def generate_restart_data
|
|
59
|
-
# Use the same trick as unicorn, namely favor PWD because
|
|
60
|
-
# it will contain an unresolved symlink, useful for when
|
|
61
|
-
# the pwd is /data/releases/current.
|
|
62
|
-
if dir = ENV['PWD']
|
|
63
|
-
s_env = File.stat(dir)
|
|
64
|
-
s_pwd = File.stat(Dir.pwd)
|
|
65
|
-
|
|
66
|
-
if s_env.ino == s_pwd.ino and s_env.dev == s_pwd.dev
|
|
67
|
-
@restart_dir = dir
|
|
68
|
-
@options[:worker_directory] = dir
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
@restart_dir ||= Dir.pwd
|
|
73
|
-
|
|
74
|
-
@original_argv = ARGV.dup
|
|
75
|
-
|
|
76
|
-
if defined? Rubinius::OS_ARGV
|
|
77
|
-
@restart_argv = Rubinius::OS_ARGV
|
|
78
|
-
else
|
|
79
|
-
require 'rubygems'
|
|
80
|
-
|
|
81
|
-
# if $0 is a file in the current directory, then restart
|
|
82
|
-
# it the same, otherwise add -S on there because it was
|
|
83
|
-
# picked up in PATH.
|
|
84
|
-
#
|
|
85
|
-
if File.exists?($0)
|
|
86
|
-
arg0 = [Gem.ruby, $0]
|
|
87
|
-
else
|
|
88
|
-
arg0 = [Gem.ruby, "-S", $0]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Detect and reinject -Ilib from the command line
|
|
92
|
-
lib = File.expand_path "lib"
|
|
93
|
-
arg0[1,0] = ["-I", lib] if $:[0] == lib
|
|
94
|
-
|
|
95
|
-
@restart_argv = arg0 + ARGV
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def restart!
|
|
100
|
-
@options[:on_restart].each do |blk|
|
|
101
|
-
blk.call self
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
if jruby?
|
|
105
|
-
@binder.listeners.each_with_index do |(str,io),i|
|
|
106
|
-
io.close
|
|
107
|
-
|
|
108
|
-
# We have to unlink a unix socket path that's not being used
|
|
109
|
-
uri = URI.parse str
|
|
110
|
-
if uri.scheme == "unix"
|
|
111
|
-
path = "#{uri.host}#{uri.path}"
|
|
112
|
-
File.unlink path
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
require 'puma/jruby_restart'
|
|
117
|
-
JRubyRestart.chdir_exec(@restart_dir, @restart_argv)
|
|
118
|
-
else
|
|
119
|
-
redirects = {:close_others => true}
|
|
120
|
-
@binder.listeners.each_with_index do |(l,io),i|
|
|
121
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
|
122
|
-
redirects[io.to_i] = io.to_i
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
if cmd = @options[:restart_cmd]
|
|
126
|
-
argv = cmd.split(' ') + @original_argv
|
|
127
|
-
else
|
|
128
|
-
argv = @restart_argv
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
Dir.chdir @restart_dir
|
|
132
|
-
|
|
133
|
-
argv += [redirects] unless RUBY_VERSION < '1.9'
|
|
134
|
-
Kernel.exec(*argv)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Delegate +log+ to +@events+
|
|
139
|
-
#
|
|
140
|
-
def log(str)
|
|
141
|
-
@events.log str
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Delegate +error+ to +@events+
|
|
145
|
-
#
|
|
146
|
-
def error(str)
|
|
147
|
-
@events.error str
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def debug(str)
|
|
151
|
-
if @options[:debug]
|
|
152
|
-
@events.log "- #{str}"
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def jruby?
|
|
157
|
-
IS_JRUBY
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def windows?
|
|
161
|
-
RUBY_PLATFORM =~ /mswin32|ming32/
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def unsupported(str, cond=true)
|
|
165
|
-
return unless cond
|
|
166
|
-
@events.error str
|
|
167
|
-
raise UnsupportedOption
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Build the OptionParser object to handle the available options.
|
|
171
|
-
#
|
|
172
|
-
def setup_options
|
|
173
|
-
@options = {
|
|
174
|
-
:min_threads => 0,
|
|
175
|
-
:max_threads => 16,
|
|
176
|
-
:quiet => false,
|
|
177
|
-
:debug => false,
|
|
178
|
-
:binds => [],
|
|
179
|
-
:workers => 0,
|
|
180
|
-
:daemon => false,
|
|
181
|
-
:worker_boot => []
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
@parser = OptionParser.new do |o|
|
|
185
|
-
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
|
186
|
-
@options[:binds] << arg
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
|
190
|
-
@options[:config_file] = arg
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
o.on "--control URL", "The bind url to use for the control server",
|
|
194
|
-
"Use 'auto' to use temp unix server" do |arg|
|
|
195
|
-
if arg
|
|
196
|
-
@options[:control_url] = arg
|
|
197
|
-
elsif jruby?
|
|
198
|
-
unsupported "No default url available on JRuby"
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
o.on "--control-token TOKEN",
|
|
203
|
-
"The token to use as authentication for the control server" do |arg|
|
|
204
|
-
@options[:control_auth_token] = arg
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
|
208
|
-
@options[:daemon] = true
|
|
209
|
-
@options[:quiet] = true
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
o.on "--debug", "Log lowlevel debugging information" do
|
|
213
|
-
@options[:debug] = true
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
|
217
|
-
@options[:directory] = d.to_s
|
|
218
|
-
@options[:worker_directory] = d.to_s
|
|
219
|
-
end
|
|
29
|
+
@argv = argv.dup
|
|
30
|
+
@log_writer = log_writer
|
|
31
|
+
@events = events
|
|
220
32
|
|
|
221
|
-
|
|
222
|
-
"The environment to run the Rack app on (default development)" do |arg|
|
|
223
|
-
@options[:environment] = arg
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
|
227
|
-
$LOAD_PATH.unshift(*arg.split(':'))
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
o.on "-p", "--port PORT", "Define what port TCP port to bind to",
|
|
231
|
-
"Use -b for more advanced options" do |arg|
|
|
232
|
-
@options[:binds] << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
|
|
233
|
-
end
|
|
33
|
+
@conf = nil
|
|
234
34
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
35
|
+
@stdout = nil
|
|
36
|
+
@stderr = nil
|
|
37
|
+
@append = false
|
|
238
38
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
end
|
|
39
|
+
@control_url = nil
|
|
40
|
+
@control_options = {}
|
|
242
41
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"Default: inferred" do |cmd|
|
|
246
|
-
@options[:restart_cmd] = cmd
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
|
250
|
-
@options[:state] = arg
|
|
251
|
-
end
|
|
42
|
+
begin
|
|
43
|
+
setup_options env
|
|
252
44
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
@options[:min_threads] = min.to_i
|
|
257
|
-
@options[:max_threads] = max.to_i
|
|
258
|
-
else
|
|
259
|
-
@options[:min_threads] = 0
|
|
260
|
-
@options[:max_threads] = arg.to_i
|
|
45
|
+
if file = @argv.shift
|
|
46
|
+
@conf.configure do |user_config, file_config|
|
|
47
|
+
file_config.rackup file
|
|
261
48
|
end
|
|
262
49
|
end
|
|
263
|
-
|
|
264
|
-
o.on "-V", "--version", "Print the version information" do
|
|
265
|
-
puts "puma version #{Puma::Const::VERSION}"
|
|
266
|
-
exit 1
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
o.on "-w", "--workers COUNT",
|
|
270
|
-
"Activate cluster mode: How many worker processes to create" do |arg|
|
|
271
|
-
@options[:workers] = arg.to_i
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
@parser.banner = "puma <options> <rackup file>"
|
|
277
|
-
|
|
278
|
-
@parser.on_tail "-h", "--help", "Show help" do
|
|
279
|
-
log @parser
|
|
50
|
+
rescue UnsupportedOption
|
|
280
51
|
exit 1
|
|
281
52
|
end
|
|
282
|
-
end
|
|
283
53
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
def write_pid
|
|
288
|
-
if path = @options[:pidfile]
|
|
289
|
-
File.open(path, "w") do |f|
|
|
290
|
-
f.puts Process.pid
|
|
54
|
+
@conf.configure do |user_config, file_config|
|
|
55
|
+
if @stdout || @stderr
|
|
56
|
+
user_config.stdout_redirect @stdout, @stderr, @append
|
|
291
57
|
end
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def set_rack_environment
|
|
296
|
-
# Try the user option first, then the environment variable,
|
|
297
|
-
# finally default to development
|
|
298
|
-
|
|
299
|
-
env = @options[:environment] ||
|
|
300
|
-
ENV['RACK_ENV'] ||
|
|
301
|
-
'development'
|
|
302
|
-
|
|
303
|
-
@options[:environment] = env
|
|
304
|
-
ENV['RACK_ENV'] = env
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
def development?
|
|
308
|
-
@options[:environment] == "development"
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def delete_pidfile
|
|
312
|
-
if path = @options[:pidfile]
|
|
313
|
-
File.unlink path
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def write_state
|
|
318
|
-
write_pid
|
|
319
|
-
|
|
320
|
-
require 'yaml'
|
|
321
|
-
|
|
322
|
-
if path = @options[:state]
|
|
323
|
-
state = { "pid" => Process.pid }
|
|
324
|
-
|
|
325
|
-
cfg = @config.dup
|
|
326
|
-
|
|
327
|
-
[ :logger, :worker_boot, :on_restart ].each { |o| cfg.options.delete o }
|
|
328
|
-
|
|
329
|
-
state["config"] = cfg
|
|
330
58
|
|
|
331
|
-
|
|
332
|
-
|
|
59
|
+
if @control_url
|
|
60
|
+
user_config.activate_control_app @control_url, @control_options
|
|
333
61
|
end
|
|
334
62
|
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
# :nodoc:
|
|
338
|
-
def parse_options
|
|
339
|
-
@parser.parse! @argv
|
|
340
|
-
|
|
341
|
-
if @argv.last
|
|
342
|
-
@options[:rackup] = @argv.shift
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
@config = Puma::Configuration.new @options
|
|
346
|
-
|
|
347
|
-
# Advertise the Configuration
|
|
348
|
-
Puma.cli_config = @config
|
|
349
|
-
|
|
350
|
-
@config.load
|
|
351
|
-
|
|
352
|
-
if @options[:workers] > 0
|
|
353
|
-
unsupported "worker mode not supported on JRuby and Windows",
|
|
354
|
-
jruby? || windows?
|
|
355
|
-
end
|
|
356
|
-
end
|
|
357
63
|
|
|
358
|
-
|
|
359
|
-
log " - Gracefully stopping, waiting for requests to finish"
|
|
360
|
-
@status.stop(true) if @status
|
|
361
|
-
server.stop(true)
|
|
362
|
-
delete_pidfile
|
|
363
|
-
log " - Goodbye!"
|
|
64
|
+
@launcher = Puma::Launcher.new(@conf, env: ENV, log_writer: @log_writer, events: @events, argv: argv)
|
|
364
65
|
end
|
|
365
66
|
|
|
366
|
-
|
|
367
|
-
stdout = @options[:redirect_stdout]
|
|
368
|
-
stderr = @options[:redirect_stderr]
|
|
369
|
-
append = @options[:redirect_append]
|
|
370
|
-
|
|
371
|
-
if stdout
|
|
372
|
-
STDOUT.reopen stdout, (append ? "a" : "w")
|
|
373
|
-
STDOUT.sync = true
|
|
374
|
-
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
if stderr
|
|
378
|
-
STDERR.reopen stderr, (append ? "a" : "w")
|
|
379
|
-
STDERR.sync = true
|
|
380
|
-
STDERR.puts "=== puma startup: #{Time.now} ==="
|
|
381
|
-
end
|
|
382
|
-
end
|
|
67
|
+
attr_reader :launcher
|
|
383
68
|
|
|
384
69
|
# Parse the options, load the rackup, start the server and wait
|
|
385
70
|
# for it to finish.
|
|
386
71
|
#
|
|
387
72
|
def run
|
|
388
|
-
|
|
389
|
-
parse_options
|
|
390
|
-
rescue UnsupportedOption
|
|
391
|
-
exit 1
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
if dir = @options[:directory]
|
|
395
|
-
Dir.chdir dir
|
|
396
|
-
end
|
|
397
|
-
|
|
398
|
-
clustered = @options[:workers] > 0
|
|
399
|
-
|
|
400
|
-
if clustered
|
|
401
|
-
@events = PidEvents.new STDOUT, STDERR
|
|
402
|
-
@options[:logger] = @events
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
set_rack_environment
|
|
406
|
-
|
|
407
|
-
if clustered
|
|
408
|
-
run_cluster
|
|
409
|
-
else
|
|
410
|
-
run_single
|
|
411
|
-
end
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
def daemon?
|
|
415
|
-
@options[:daemon]
|
|
73
|
+
@launcher.run
|
|
416
74
|
end
|
|
417
75
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
def output_header
|
|
423
|
-
min_t = @options[:min_threads]
|
|
424
|
-
max_t = @options[:max_threads]
|
|
425
|
-
|
|
426
|
-
log "Puma #{Puma::Const::PUMA_VERSION} starting..."
|
|
427
|
-
log "* Min threads: #{min_t}, max threads: #{max_t}"
|
|
428
|
-
log "* Environment: #{ENV['RACK_ENV']}"
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
def start_control(server, str)
|
|
432
|
-
require 'puma/app/status'
|
|
433
|
-
|
|
434
|
-
uri = URI.parse str
|
|
435
|
-
|
|
436
|
-
app = Puma::App::Status.new server, self
|
|
437
|
-
|
|
438
|
-
if token = @options[:control_auth_token]
|
|
439
|
-
app.auth_token = token unless token.empty? or token == :none
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
status = Puma::Server.new app, @events
|
|
443
|
-
status.min_threads = 0
|
|
444
|
-
status.max_threads = 1
|
|
445
|
-
|
|
446
|
-
case uri.scheme
|
|
447
|
-
when "tcp"
|
|
448
|
-
log "* Starting status server on #{str}"
|
|
449
|
-
status.add_tcp_listener uri.host, uri.port
|
|
450
|
-
when "unix"
|
|
451
|
-
log "* Starting status server on #{str}"
|
|
452
|
-
path = "#{uri.host}#{uri.path}"
|
|
453
|
-
|
|
454
|
-
status.add_unix_listener path
|
|
455
|
-
else
|
|
456
|
-
error "Invalid status URI: #{str}"
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
status.run
|
|
460
|
-
@status = status
|
|
76
|
+
private
|
|
77
|
+
def unsupported(str)
|
|
78
|
+
@log_writer.error(str)
|
|
79
|
+
raise UnsupportedOption
|
|
461
80
|
end
|
|
462
81
|
|
|
463
|
-
def
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
# Load the app before we daemonize.
|
|
470
|
-
begin
|
|
471
|
-
@app = @config.app
|
|
472
|
-
rescue Exception => e
|
|
473
|
-
log "! Unable to load application"
|
|
474
|
-
raise e
|
|
82
|
+
def configure_control_url(command_line_arg)
|
|
83
|
+
if command_line_arg
|
|
84
|
+
@control_url = command_line_arg
|
|
85
|
+
elsif Puma.jruby?
|
|
86
|
+
unsupported "No default url available on JRuby"
|
|
475
87
|
end
|
|
476
|
-
|
|
477
|
-
@binder.parse @options[:binds], self
|
|
478
88
|
end
|
|
479
89
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if jruby_daemon?
|
|
484
|
-
require 'puma/jruby_restart'
|
|
485
|
-
|
|
486
|
-
if JRubyRestart.daemon?
|
|
487
|
-
# load and bind before redirecting IO so errors show up on stdout/stderr
|
|
488
|
-
load_and_bind
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
already_daemon = JRubyRestart.daemon_init
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
output_header
|
|
495
|
-
|
|
496
|
-
if jruby_daemon?
|
|
497
|
-
unless already_daemon
|
|
498
|
-
require 'puma/jruby_restart'
|
|
499
|
-
|
|
500
|
-
pid = nil
|
|
90
|
+
# Build the OptionParser object to handle the available options.
|
|
91
|
+
#
|
|
501
92
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
93
|
+
def setup_options(env = ENV)
|
|
94
|
+
@conf = Configuration.new({}, { events: @events }, env) do |user_config, file_config|
|
|
95
|
+
@parser = OptionParser.new do |o|
|
|
96
|
+
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
|
97
|
+
user_config.bind arg
|
|
505
98
|
end
|
|
506
99
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
else
|
|
511
|
-
load_and_bind
|
|
512
|
-
Process.daemon(true) if daemon?
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
write_state
|
|
516
|
-
|
|
517
|
-
server = Puma::Server.new @app, @events
|
|
518
|
-
server.binder = @binder
|
|
519
|
-
server.min_threads = @options[:min_threads]
|
|
520
|
-
server.max_threads = @options[:max_threads]
|
|
521
|
-
|
|
522
|
-
unless development?
|
|
523
|
-
server.leak_stack_on_error = false
|
|
524
|
-
end
|
|
525
|
-
|
|
526
|
-
@server = server
|
|
527
|
-
|
|
528
|
-
if str = @options[:control_url]
|
|
529
|
-
start_control server, str
|
|
530
|
-
end
|
|
531
|
-
|
|
532
|
-
begin
|
|
533
|
-
Signal.trap "SIGUSR2" do
|
|
534
|
-
@restart = true
|
|
535
|
-
server.begin_restart
|
|
536
|
-
end
|
|
537
|
-
rescue Exception
|
|
538
|
-
log "*** Sorry signal SIGUSR2 not implemented, restart feature disabled!"
|
|
539
|
-
end
|
|
540
|
-
|
|
541
|
-
begin
|
|
542
|
-
Signal.trap "SIGTERM" do
|
|
543
|
-
log " - Gracefully stopping, waiting for requests to finish"
|
|
544
|
-
server.stop false
|
|
545
|
-
end
|
|
546
|
-
rescue Exception
|
|
547
|
-
log "*** Sorry signal SIGTERM not implemented, gracefully stopping feature disabled!"
|
|
548
|
-
end
|
|
549
|
-
|
|
550
|
-
unless @options[:daemon]
|
|
551
|
-
log "Use Ctrl-C to stop"
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
redirect_io
|
|
555
|
-
|
|
556
|
-
if jruby?
|
|
557
|
-
Signal.trap("INT") do
|
|
558
|
-
graceful_stop server
|
|
559
|
-
exit
|
|
560
|
-
end
|
|
561
|
-
end
|
|
562
|
-
|
|
563
|
-
begin
|
|
564
|
-
server.run.join
|
|
565
|
-
rescue Interrupt
|
|
566
|
-
graceful_stop server
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
if @restart
|
|
570
|
-
log "* Restarting..."
|
|
571
|
-
@status.stop true if @status
|
|
572
|
-
restart!
|
|
573
|
-
end
|
|
574
|
-
end
|
|
575
|
-
|
|
576
|
-
def worker(upgrade)
|
|
577
|
-
$0 = "puma: cluster worker: #{@master_pid}"
|
|
578
|
-
Signal.trap "SIGINT", "IGNORE"
|
|
579
|
-
|
|
580
|
-
@master_read.close
|
|
581
|
-
@suicide_pipe.close
|
|
582
|
-
|
|
583
|
-
Thread.new do
|
|
584
|
-
IO.select [@check_pipe]
|
|
585
|
-
log "! Detected parent died, dying"
|
|
586
|
-
exit! 1
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
# Be sure to change the directory again before loading
|
|
590
|
-
# the app. This way we can pick up new code.
|
|
591
|
-
if upgrade
|
|
592
|
-
if dir = @options[:worker_directory]
|
|
593
|
-
log "+ Changing to #{dir}"
|
|
594
|
-
Dir.chdir dir
|
|
595
|
-
end
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
# Invoke any worker boot hooks so they can get
|
|
599
|
-
# things in shape before booting the app.
|
|
600
|
-
hooks = @options[:worker_boot]
|
|
601
|
-
hooks.each { |h| h.call }
|
|
602
|
-
|
|
603
|
-
min_t = @options[:min_threads]
|
|
604
|
-
max_t = @options[:max_threads]
|
|
605
|
-
|
|
606
|
-
# If preload is used, then @app is set to the preloaded
|
|
607
|
-
# application. Otherwise load it now via the config.
|
|
608
|
-
app = @app || @config.app
|
|
609
|
-
|
|
610
|
-
server = Puma::Server.new app, @events
|
|
611
|
-
server.min_threads = min_t
|
|
612
|
-
server.max_threads = max_t
|
|
613
|
-
server.inherit_binder @binder
|
|
614
|
-
|
|
615
|
-
unless development?
|
|
616
|
-
server.leak_stack_on_error = false
|
|
617
|
-
end
|
|
618
|
-
|
|
619
|
-
Signal.trap "SIGTERM" do
|
|
620
|
-
server.stop
|
|
621
|
-
end
|
|
622
|
-
|
|
623
|
-
begin
|
|
624
|
-
@worker_write << "b#{Process.pid}\n"
|
|
625
|
-
rescue SystemCallError, IOError
|
|
626
|
-
STDERR.puts "Master seems to have exitted, exitting."
|
|
627
|
-
return
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
server.run.join
|
|
631
|
-
|
|
632
|
-
ensure
|
|
633
|
-
@worker_write.close
|
|
634
|
-
end
|
|
635
|
-
|
|
636
|
-
def stop_workers
|
|
637
|
-
log "- Gracefully shutting down workers..."
|
|
638
|
-
@workers.each { |x| x.term }
|
|
639
|
-
|
|
640
|
-
begin
|
|
641
|
-
Process.waitall
|
|
642
|
-
rescue Interrupt
|
|
643
|
-
log "! Cancelled waiting for workers"
|
|
644
|
-
else
|
|
645
|
-
log "- Goodbye!"
|
|
646
|
-
end
|
|
647
|
-
end
|
|
648
|
-
|
|
649
|
-
def start_phased_restart
|
|
650
|
-
@phase += 1
|
|
651
|
-
log "- Starting phased worker restart, phase: #{@phase}"
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
class Worker
|
|
655
|
-
def initialize(pid, phase)
|
|
656
|
-
@pid = pid
|
|
657
|
-
@phase = phase
|
|
658
|
-
@stage = :started
|
|
659
|
-
end
|
|
660
|
-
|
|
661
|
-
attr_reader :pid, :phase
|
|
662
|
-
|
|
663
|
-
def booted?
|
|
664
|
-
@stage == :booted
|
|
665
|
-
end
|
|
666
|
-
|
|
667
|
-
def boot!
|
|
668
|
-
@stage = :booted
|
|
669
|
-
end
|
|
670
|
-
|
|
671
|
-
def term
|
|
672
|
-
begin
|
|
673
|
-
Process.kill "TERM", @pid
|
|
674
|
-
rescue Errno::ESRCH
|
|
675
|
-
end
|
|
676
|
-
end
|
|
677
|
-
end
|
|
678
|
-
|
|
679
|
-
def spawn_workers
|
|
680
|
-
diff = @options[:workers] - @workers.size
|
|
681
|
-
|
|
682
|
-
upgrade = (@phased_state == :waiting)
|
|
683
|
-
|
|
684
|
-
diff.times do
|
|
685
|
-
pid = fork { worker(upgrade) }
|
|
686
|
-
debug "Spawned worker: #{pid}"
|
|
687
|
-
@workers << Worker.new(pid, @phase)
|
|
688
|
-
end
|
|
100
|
+
o.on "--bind-to-activated-sockets [only]", "Bind to all activated sockets" do |arg|
|
|
101
|
+
user_config.bind_to_activated_sockets(arg || true)
|
|
102
|
+
end
|
|
689
103
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
end
|
|
104
|
+
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
|
105
|
+
file_config.load arg
|
|
106
|
+
end
|
|
694
107
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
108
|
+
# Identical to supplying --config "-", but more semantic
|
|
109
|
+
o.on "--no-config", "Prevent Puma from searching for a config file" do |arg|
|
|
110
|
+
file_config.load "-"
|
|
111
|
+
end
|
|
698
112
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
break unless pid
|
|
113
|
+
o.on "--control-url URL", "The bind url to use for the control server. Use 'auto' to use temp unix server" do |arg|
|
|
114
|
+
configure_control_url(arg)
|
|
115
|
+
end
|
|
703
116
|
|
|
704
|
-
|
|
705
|
-
|
|
117
|
+
o.on "--control-token TOKEN",
|
|
118
|
+
"The token to use as authentication for the control server" do |arg|
|
|
119
|
+
@control_options[:auth_token] = arg
|
|
120
|
+
end
|
|
706
121
|
|
|
707
|
-
|
|
122
|
+
o.on "--debug", "Log lowlevel debugging information" do
|
|
123
|
+
user_config.debug
|
|
124
|
+
end
|
|
708
125
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
# in the right phase).
|
|
713
|
-
#
|
|
714
|
-
w = @workers.find { |x| x.phase != @phase }
|
|
126
|
+
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
|
127
|
+
user_config.directory d
|
|
128
|
+
end
|
|
715
129
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
end
|
|
721
|
-
end
|
|
722
|
-
end
|
|
130
|
+
o.on "-e", "--environment ENVIRONMENT",
|
|
131
|
+
"The environment to run the Rack app on (default development)" do |arg|
|
|
132
|
+
user_config.environment arg
|
|
133
|
+
end
|
|
723
134
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
end
|
|
135
|
+
o.on "-f", "--fork-worker=[REQUESTS]", OptionParser::DecimalInteger,
|
|
136
|
+
"Fork new workers from existing worker. Cluster mode only",
|
|
137
|
+
"Auto-refork after REQUESTS (default 1000)" do |*args|
|
|
138
|
+
user_config.fork_worker(*args.compact)
|
|
139
|
+
end
|
|
730
140
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
log "* Min threads: #{@options[:min_threads]}, max threads: #{@options[:max_threads]}"
|
|
735
|
-
log "* Environment: #{ENV['RACK_ENV']}"
|
|
736
|
-
|
|
737
|
-
if @options[:preload_app]
|
|
738
|
-
log "* Preloading application"
|
|
739
|
-
load_and_bind
|
|
740
|
-
else
|
|
741
|
-
log "* Phased restart available"
|
|
742
|
-
|
|
743
|
-
unless @config.app_configured?
|
|
744
|
-
error "No application configured, nothing to run"
|
|
745
|
-
exit 1
|
|
746
|
-
end
|
|
141
|
+
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
|
142
|
+
$LOAD_PATH.unshift(*arg.split(':'))
|
|
143
|
+
end
|
|
747
144
|
|
|
748
|
-
|
|
749
|
-
|
|
145
|
+
o.on "--idle-timeout SECONDS", "Number of seconds until the next request before automatic shutdown" do |arg|
|
|
146
|
+
user_config.idle_timeout arg
|
|
147
|
+
end
|
|
750
148
|
|
|
751
|
-
|
|
149
|
+
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
|
150
|
+
"Use -b for more advanced options" do |arg|
|
|
151
|
+
user_config.port arg, Configuration.default_tcp_host
|
|
152
|
+
end
|
|
752
153
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
154
|
+
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
|
|
155
|
+
user_config.pidfile arg
|
|
156
|
+
end
|
|
756
157
|
|
|
757
|
-
|
|
158
|
+
o.on "--plugin PLUGIN", "Load the given PLUGIN. Can be used multiple times to load multiple plugins." do |arg|
|
|
159
|
+
user_config.plugin arg
|
|
160
|
+
end
|
|
758
161
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
stop = true
|
|
763
|
-
wakeup!
|
|
764
|
-
end
|
|
765
|
-
rescue Exception
|
|
766
|
-
end
|
|
162
|
+
o.on "--preload", "Preload the app. Cluster mode only" do
|
|
163
|
+
user_config.preload_app!
|
|
164
|
+
end
|
|
767
165
|
|
|
768
|
-
|
|
166
|
+
o.on "--prune-bundler", "Prune out the bundler env if possible" do
|
|
167
|
+
user_config.prune_bundler
|
|
168
|
+
end
|
|
769
169
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
# The worker installs their own SIGTERM when booted.
|
|
773
|
-
# Until then, this is run by the worker and the worker
|
|
774
|
-
# should just exit if they get it.
|
|
775
|
-
if Process.pid != master_pid
|
|
776
|
-
log "Early termination of worker"
|
|
777
|
-
exit! 0
|
|
778
|
-
else
|
|
779
|
-
stop = true
|
|
780
|
-
wakeup!
|
|
170
|
+
o.on "--extra-runtime-dependencies GEM1,GEM2", "Defines any extra needed gems when using --prune-bundler" do |arg|
|
|
171
|
+
user_config.extra_runtime_dependencies arg.split(',')
|
|
781
172
|
end
|
|
782
|
-
end
|
|
783
|
-
rescue Exception
|
|
784
|
-
end
|
|
785
173
|
|
|
786
|
-
|
|
174
|
+
o.on "-q", "--quiet", "Do not log requests internally (default true)" do
|
|
175
|
+
user_config.quiet
|
|
176
|
+
end
|
|
787
177
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
Signal.trap "SIGUSR1" do
|
|
791
|
-
log "App preloaded, phased restart unavailable"
|
|
178
|
+
o.on "-v", "--log-requests", "Log requests as they occur" do
|
|
179
|
+
user_config.log_requests
|
|
792
180
|
end
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
181
|
+
|
|
182
|
+
o.on "-R", "--restart-cmd CMD",
|
|
183
|
+
"The puma command to run during a hot restart",
|
|
184
|
+
"Default: inferred" do |cmd|
|
|
185
|
+
user_config.restart_command cmd
|
|
798
186
|
end
|
|
799
|
-
end
|
|
800
|
-
rescue Exception
|
|
801
|
-
end
|
|
802
187
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
# closed.
|
|
807
|
-
#
|
|
808
|
-
@check_pipe, @suicide_pipe = Puma::Util.pipe
|
|
809
|
-
|
|
810
|
-
if @options[:daemon]
|
|
811
|
-
Process.daemon(true)
|
|
812
|
-
else
|
|
813
|
-
log "Use Ctrl-C to stop"
|
|
814
|
-
end
|
|
188
|
+
o.on "-s", "--silent", "Do not log prompt messages other than errors" do
|
|
189
|
+
@log_writer = LogWriter.new(NullIO.new, $stderr)
|
|
190
|
+
end
|
|
815
191
|
|
|
816
|
-
|
|
192
|
+
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
|
193
|
+
user_config.state_path arg
|
|
194
|
+
end
|
|
817
195
|
|
|
818
|
-
|
|
196
|
+
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
|
|
197
|
+
min, max = arg.split(":")
|
|
198
|
+
if max
|
|
199
|
+
user_config.threads min, max
|
|
200
|
+
else
|
|
201
|
+
user_config.threads min, min
|
|
202
|
+
end
|
|
203
|
+
end
|
|
819
204
|
|
|
820
|
-
|
|
205
|
+
o.on "--early-hints", "Enable early hints support" do
|
|
206
|
+
user_config.early_hints
|
|
207
|
+
end
|
|
821
208
|
|
|
822
|
-
|
|
823
|
-
|
|
209
|
+
o.on "-V", "--version", "Print the version information" do
|
|
210
|
+
puts "puma version #{Puma::Const::VERSION}"
|
|
211
|
+
exit 0
|
|
212
|
+
end
|
|
824
213
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
214
|
+
o.on "-w", "--workers COUNT",
|
|
215
|
+
"Activate cluster mode: How many worker processes to create" do |arg|
|
|
216
|
+
user_config.workers arg
|
|
217
|
+
end
|
|
829
218
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
res = IO.select([read], nil, nil, 5)
|
|
834
|
-
|
|
835
|
-
if res
|
|
836
|
-
req = read.read_nonblock(1)
|
|
837
|
-
|
|
838
|
-
if req == "b"
|
|
839
|
-
pid = read.gets.to_i
|
|
840
|
-
w = @workers.find { |x| x.pid == pid }
|
|
841
|
-
if w
|
|
842
|
-
w.boot!
|
|
843
|
-
log "- Worker #{pid} booted, phase: #{w.phase}"
|
|
844
|
-
else
|
|
845
|
-
log "! Out-of-sync worker list, no #{pid} worker"
|
|
846
|
-
end
|
|
847
|
-
end
|
|
848
|
-
end
|
|
219
|
+
o.on "--tag NAME", "Additional text to display in process listing" do |arg|
|
|
220
|
+
user_config.tag arg
|
|
221
|
+
end
|
|
849
222
|
|
|
850
|
-
|
|
223
|
+
o.on "--redirect-stdout FILE", "Redirect STDOUT to a specific file" do |arg|
|
|
224
|
+
@stdout = arg.to_s
|
|
225
|
+
end
|
|
851
226
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
end
|
|
227
|
+
o.on "--redirect-stderr FILE", "Redirect STDERR to a specific file" do |arg|
|
|
228
|
+
@stderr = arg.to_s
|
|
229
|
+
end
|
|
856
230
|
|
|
857
|
-
|
|
858
|
-
|
|
231
|
+
o.on "--[no-]redirect-append", "Append to redirected files" do |val|
|
|
232
|
+
@append = val
|
|
859
233
|
end
|
|
860
|
-
end
|
|
861
234
|
|
|
862
|
-
|
|
863
|
-
ensure
|
|
864
|
-
delete_pidfile
|
|
865
|
-
@check_pipe.close
|
|
866
|
-
@suicide_pipe.close
|
|
867
|
-
read.close
|
|
868
|
-
@wakeup.close
|
|
869
|
-
end
|
|
235
|
+
o.banner = "puma <options> <rackup file>"
|
|
870
236
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
237
|
+
o.on_tail "-h", "--help", "Show help" do
|
|
238
|
+
$stdout.puts o
|
|
239
|
+
exit 0
|
|
240
|
+
end
|
|
241
|
+
end.parse! @argv
|
|
874
242
|
end
|
|
875
243
|
end
|
|
876
|
-
|
|
877
|
-
def stop
|
|
878
|
-
@status.stop(true) if @status
|
|
879
|
-
@server.stop(true) if @server
|
|
880
|
-
delete_pidfile
|
|
881
|
-
end
|
|
882
244
|
end
|
|
883
245
|
end
|