puma 2.16.0 → 3.11.4
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 +5 -5
- data/{History.txt → History.md} +489 -70
- data/README.md +143 -174
- data/docs/architecture.md +36 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +1 -1
- 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/nginx.md +2 -2
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +272 -0
- data/ext/puma_http11/extconf.rb +2 -0
- data/ext/puma_http11/http11_parser.c +291 -447
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +8 -8
- data/ext/puma_http11/mini_ssl.c +64 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +113 -131
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +9 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma/app/status.rb +9 -1
- data/lib/puma/binder.rb +90 -38
- data/lib/puma/cli.rb +134 -491
- data/lib/puma/client.rb +142 -4
- data/lib/puma/cluster.rb +132 -76
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +206 -67
- data/lib/puma/const.rb +21 -31
- data/lib/puma/control_cli.rb +92 -103
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +6 -0
- data/lib/puma/detect.rb +10 -1
- data/lib/puma/dsl.rb +203 -45
- data/lib/puma/events.rb +22 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +1 -2
- data/lib/puma/launcher.rb +431 -0
- data/lib/puma/minissl.rb +83 -4
- data/lib/puma/null_io.rb +19 -11
- data/lib/puma/plugin/tmp_restart.rb +34 -0
- data/lib/puma/plugin.rb +115 -0
- data/lib/puma/rack/backports/uri/common_193.rb +17 -13
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +18 -0
- data/lib/puma/runner.rb +43 -15
- data/lib/puma/server.rb +141 -35
- data/lib/puma/single.rb +16 -6
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +60 -10
- data/lib/puma/util.rb +1 -5
- data/lib/puma.rb +13 -4
- data/lib/rack/handler/puma.rb +76 -29
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +86 -59
- data/tools/jungle/init.d/run-puma +16 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/jungle/upstart/puma.conf +1 -1
- data/tools/trickletest.rb +1 -1
- metadata +28 -95
- data/COPYING +0 -55
- data/Gemfile +0 -13
- data/Manifest.txt +0 -74
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/capistrano.rb +0 -94
- data/lib/puma/rack/backports/uri/common_18.rb +0 -56
- data/lib/puma/rack/backports/uri/common_192.rb +0 -52
- data/puma.gemspec +0 -52
data/lib/puma/control_cli.rb
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
require 'optparse'
|
|
2
|
+
require 'puma/state_file'
|
|
2
3
|
require 'puma/const'
|
|
4
|
+
require 'puma/detect'
|
|
3
5
|
require 'puma/configuration'
|
|
4
|
-
require 'yaml'
|
|
5
6
|
require 'uri'
|
|
6
7
|
require 'socket'
|
|
8
|
+
|
|
7
9
|
module Puma
|
|
8
10
|
class ControlCLI
|
|
9
11
|
|
|
10
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
|
11
|
-
|
|
12
|
-
def is_windows?
|
|
13
|
-
RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
|
|
14
|
-
end
|
|
12
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
|
15
13
|
|
|
16
14
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
|
17
|
-
@
|
|
15
|
+
@state = nil
|
|
16
|
+
@quiet = false
|
|
17
|
+
@pidfile = nil
|
|
18
|
+
@pid = nil
|
|
19
|
+
@control_url = nil
|
|
20
|
+
@control_auth_token = nil
|
|
21
|
+
@config_file = nil
|
|
22
|
+
@command = nil
|
|
23
|
+
|
|
24
|
+
@argv = argv.dup
|
|
18
25
|
@stdout = stdout
|
|
19
26
|
@stderr = stderr
|
|
20
27
|
@cli_options = {}
|
|
@@ -23,31 +30,31 @@ module Puma
|
|
|
23
30
|
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{COMMANDS.join("|")})"
|
|
24
31
|
|
|
25
32
|
o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
|
|
26
|
-
@
|
|
33
|
+
@state = arg
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
o.on "-Q", "--quiet", "Not display messages" do |arg|
|
|
30
|
-
@
|
|
37
|
+
@quiet = true
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
o.on "-P", "--pidfile PATH", "Pid file" do |arg|
|
|
34
|
-
@
|
|
41
|
+
@pidfile = arg
|
|
35
42
|
end
|
|
36
43
|
|
|
37
44
|
o.on "-p", "--pid PID", "Pid" do |arg|
|
|
38
|
-
@
|
|
45
|
+
@pid = arg.to_i
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
o.on "-C", "--control-url URL", "The bind url to use for the control server" do |arg|
|
|
42
|
-
@
|
|
49
|
+
@control_url = arg
|
|
43
50
|
end
|
|
44
51
|
|
|
45
52
|
o.on "-T", "--control-token TOKEN", "The token to use as authentication for the control server" do |arg|
|
|
46
|
-
@
|
|
53
|
+
@control_auth_token = arg
|
|
47
54
|
end
|
|
48
55
|
|
|
49
56
|
o.on "-F", "--config-file PATH", "Puma config script" do |arg|
|
|
50
|
-
@
|
|
57
|
+
@config_file = arg
|
|
51
58
|
end
|
|
52
59
|
|
|
53
60
|
o.on_tail("-H", "--help", "Show this message") do
|
|
@@ -62,80 +69,64 @@ module Puma
|
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
opts.order!(argv) { |a| opts.terminate a }
|
|
72
|
+
opts.parse!
|
|
65
73
|
|
|
66
|
-
command = argv.shift
|
|
67
|
-
@cli_options[:command] = command if command
|
|
68
|
-
|
|
69
|
-
@options = nil
|
|
74
|
+
@command = argv.shift
|
|
70
75
|
|
|
71
|
-
unless @
|
|
72
|
-
if @
|
|
73
|
-
@
|
|
76
|
+
unless @config_file == '-'
|
|
77
|
+
if @config_file.nil? and File.exist?('config/puma.rb')
|
|
78
|
+
@config_file = 'config/puma.rb'
|
|
74
79
|
end
|
|
75
80
|
|
|
76
|
-
if @
|
|
77
|
-
config = Puma::Configuration.new(@
|
|
81
|
+
if @config_file
|
|
82
|
+
config = Puma::Configuration.new({ config_files: [@config_file] }, {})
|
|
78
83
|
config.load
|
|
79
|
-
@
|
|
84
|
+
@state ||= config.options[:state]
|
|
85
|
+
@control_url ||= config.options[:control_url]
|
|
86
|
+
@control_auth_token ||= config.options[:control_auth_token]
|
|
87
|
+
@pidfile ||= config.options[:pidfile]
|
|
80
88
|
end
|
|
81
89
|
end
|
|
82
90
|
|
|
83
|
-
@options ||= @cli_options
|
|
84
|
-
|
|
85
91
|
# check present of command
|
|
86
|
-
unless @
|
|
92
|
+
unless @command
|
|
87
93
|
raise "Available commands: #{COMMANDS.join(", ")}"
|
|
88
94
|
end
|
|
89
95
|
|
|
90
|
-
unless COMMANDS.include? @
|
|
91
|
-
raise "Invalid command: #{@
|
|
96
|
+
unless COMMANDS.include? @command
|
|
97
|
+
raise "Invalid command: #{@command}"
|
|
92
98
|
end
|
|
93
99
|
|
|
94
100
|
rescue => e
|
|
95
101
|
@stdout.puts e.message
|
|
102
|
+
@stdout.puts e.backtrace
|
|
96
103
|
exit 1
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
def message(msg)
|
|
100
|
-
@stdout.puts msg unless @
|
|
107
|
+
@stdout.puts msg unless @quiet
|
|
101
108
|
end
|
|
102
109
|
|
|
103
110
|
def prepare_configuration
|
|
104
|
-
if @
|
|
105
|
-
unless File.exist? @
|
|
106
|
-
raise "
|
|
111
|
+
if @state
|
|
112
|
+
unless File.exist? @state
|
|
113
|
+
raise "State file not found: #{@state}"
|
|
107
114
|
end
|
|
108
115
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if status.kind_of?(Hash) && status.has_key?("config")
|
|
112
|
-
|
|
113
|
-
conf = status["config"]
|
|
114
|
-
|
|
115
|
-
# get control_url
|
|
116
|
-
if url = conf.options[:control_url]
|
|
117
|
-
@options[:control_url] = url
|
|
118
|
-
end
|
|
116
|
+
sf = Puma::StateFile.new
|
|
117
|
+
sf.load @state
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
# get pid
|
|
126
|
-
@options[:pid] = status["pid"].to_i
|
|
127
|
-
else
|
|
128
|
-
raise "Invalid status file: #{@options[:state]}"
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
elsif @options.has_key? :pidfile
|
|
119
|
+
@control_url = sf.control_url
|
|
120
|
+
@control_auth_token = sf.control_auth_token
|
|
121
|
+
@pid = sf.pid
|
|
122
|
+
elsif @pidfile
|
|
132
123
|
# get pid from pid_file
|
|
133
|
-
@
|
|
124
|
+
@pid = File.open(@pidfile).gets.to_i
|
|
134
125
|
end
|
|
135
126
|
end
|
|
136
127
|
|
|
137
128
|
def send_request
|
|
138
|
-
uri = URI.parse @
|
|
129
|
+
uri = URI.parse @control_url
|
|
139
130
|
|
|
140
131
|
# create server object by scheme
|
|
141
132
|
@server = case uri.scheme
|
|
@@ -147,13 +138,13 @@ module Puma
|
|
|
147
138
|
raise "Invalid scheme: #{uri.scheme}"
|
|
148
139
|
end
|
|
149
140
|
|
|
150
|
-
if @
|
|
141
|
+
if @command == "status"
|
|
151
142
|
message "Puma is started"
|
|
152
143
|
else
|
|
153
|
-
url = "/#{@
|
|
144
|
+
url = "/#{@command}"
|
|
154
145
|
|
|
155
|
-
if @
|
|
156
|
-
url = url + "?token=#{@
|
|
146
|
+
if @control_auth_token
|
|
147
|
+
url = url + "?token=#{@control_auth_token}"
|
|
157
148
|
end
|
|
158
149
|
|
|
159
150
|
@server << "GET #{url} HTTP/1.0\r\n\r\n"
|
|
@@ -178,71 +169,70 @@ module Puma
|
|
|
178
169
|
raise "Bad response from server: #{@code}"
|
|
179
170
|
end
|
|
180
171
|
|
|
181
|
-
message "Command #{@
|
|
182
|
-
message response.last if @
|
|
172
|
+
message "Command #{@command} sent success"
|
|
173
|
+
message response.last if @command == "stats" || @command == "gc-stats"
|
|
183
174
|
end
|
|
184
175
|
|
|
185
176
|
@server.close
|
|
186
177
|
end
|
|
187
178
|
|
|
188
179
|
def send_signal
|
|
189
|
-
unless
|
|
180
|
+
unless @pid
|
|
190
181
|
raise "Neither pid nor control url available"
|
|
191
182
|
end
|
|
192
183
|
|
|
193
184
|
begin
|
|
194
|
-
Process.getpgid pid
|
|
195
|
-
rescue SystemCallError
|
|
196
|
-
if @options[:command] == "restart"
|
|
197
|
-
@options.delete(:command)
|
|
198
|
-
start
|
|
199
|
-
else
|
|
200
|
-
raise "No pid '#{pid}' found"
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
185
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
186
|
+
case @command
|
|
187
|
+
when "restart"
|
|
188
|
+
Process.kill "SIGUSR2", @pid
|
|
207
189
|
|
|
208
|
-
|
|
209
|
-
|
|
190
|
+
when "halt"
|
|
191
|
+
Process.kill "QUIT", @pid
|
|
210
192
|
|
|
211
|
-
|
|
212
|
-
|
|
193
|
+
when "stop"
|
|
194
|
+
Process.kill "SIGTERM", @pid
|
|
213
195
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
196
|
+
when "stats"
|
|
197
|
+
puts "Stats not available via pid only"
|
|
198
|
+
return
|
|
217
199
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
200
|
+
when "reload-worker-directory"
|
|
201
|
+
puts "reload-worker-directory not available via pid only"
|
|
202
|
+
return
|
|
221
203
|
|
|
222
|
-
|
|
223
|
-
|
|
204
|
+
when "phased-restart"
|
|
205
|
+
Process.kill "SIGUSR1", @pid
|
|
224
206
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
207
|
+
else
|
|
208
|
+
return
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
rescue SystemCallError
|
|
212
|
+
if @command == "restart"
|
|
213
|
+
start
|
|
214
|
+
else
|
|
215
|
+
raise "No pid '#{@pid}' found"
|
|
216
|
+
end
|
|
228
217
|
end
|
|
229
218
|
|
|
230
|
-
message "Command #{@
|
|
219
|
+
message "Command #{@command} sent success"
|
|
231
220
|
end
|
|
232
221
|
|
|
233
222
|
def run
|
|
234
|
-
start if @
|
|
223
|
+
start if @command == "start"
|
|
235
224
|
|
|
236
225
|
prepare_configuration
|
|
237
226
|
|
|
238
|
-
if
|
|
227
|
+
if Puma.windows?
|
|
239
228
|
send_request
|
|
240
229
|
else
|
|
241
|
-
@
|
|
230
|
+
@control_url ? send_request : send_signal
|
|
242
231
|
end
|
|
243
232
|
|
|
244
233
|
rescue => e
|
|
245
234
|
message e.message
|
|
235
|
+
message e.backtrace
|
|
246
236
|
exit 1
|
|
247
237
|
end
|
|
248
238
|
|
|
@@ -250,15 +240,14 @@ module Puma
|
|
|
250
240
|
def start
|
|
251
241
|
require 'puma/cli'
|
|
252
242
|
|
|
253
|
-
run_args =
|
|
243
|
+
run_args = []
|
|
254
244
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
end
|
|
245
|
+
run_args += ["-S", @state] if @state
|
|
246
|
+
run_args += ["-q"] if @quiet
|
|
247
|
+
run_args += ["--pidfile", @pidfile] if @pidfile
|
|
248
|
+
run_args += ["--control-url", @control_url] if @control_url
|
|
249
|
+
run_args += ["--control-token", @control_auth_token] if @control_auth_token
|
|
250
|
+
run_args += ["-C", @config_file] if @config_file
|
|
262
251
|
|
|
263
252
|
events = Puma::Events.new @stdout, @stderr
|
|
264
253
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'puma/launcher'
|
|
2
|
+
require 'puma/configuration'
|
|
3
|
+
|
|
4
|
+
module Puma
|
|
5
|
+
def self.run(opts={})
|
|
6
|
+
cfg = Puma::Configuration.new do |user_config|
|
|
7
|
+
if port = opts[:port]
|
|
8
|
+
user_config.port port
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
user_config.quiet
|
|
12
|
+
|
|
13
|
+
yield c
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
cfg.clamp
|
|
17
|
+
|
|
18
|
+
events = Puma::Events.null
|
|
19
|
+
|
|
20
|
+
launcher = Puma::Launcher.new cfg, :events => events
|
|
21
|
+
launcher.run
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/puma/daemon_ext.rb
CHANGED
|
@@ -3,6 +3,12 @@ module Process
|
|
|
3
3
|
# This overrides the default version because it is broken if it
|
|
4
4
|
# exists.
|
|
5
5
|
|
|
6
|
+
if respond_to? :daemon
|
|
7
|
+
class << self
|
|
8
|
+
remove_method :daemon
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
6
12
|
def self.daemon(nochdir=false, noclose=false)
|
|
7
13
|
exit if fork # Parent exits, child continues.
|
|
8
14
|
|