puma 3.12.6 → 5.3.2
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 +1400 -451
- data/LICENSE +23 -20
- data/README.md +131 -60
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +24 -19
- data/docs/compile_options.md +19 -0
- data/docs/deployment.md +38 -13
- 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 +20 -10
- data/docs/rails_dev_mode.md +29 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +7 -6
- data/docs/stats.md +142 -0
- data/docs/systemd.md +48 -70
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +27 -0
- data/ext/puma_http11/http11_parser.c +81 -108
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/mini_ssl.c +254 -91
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +89 -106
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +92 -22
- data/ext/puma_http11/puma_http11.c +34 -50
- data/lib/puma.rb +54 -0
- data/lib/puma/app/status.rb +68 -49
- data/lib/puma/binder.rb +191 -139
- data/lib/puma/cli.rb +15 -15
- data/lib/puma/client.rb +247 -226
- data/lib/puma/cluster.rb +221 -212
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +90 -0
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -51
- data/lib/puma/const.rb +32 -20
- data/lib/puma/control_cli.rb +109 -67
- data/lib/puma/detect.rb +24 -3
- data/lib/puma/dsl.rb +519 -121
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -31
- data/lib/puma/io_buffer.rb +7 -5
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json.rb +96 -0
- data/lib/puma/launcher.rb +178 -68
- data/lib/puma/minissl.rb +147 -48
- data/lib/puma/minissl/context_builder.rb +79 -0
- data/lib/puma/null_io.rb +13 -1
- data/lib/puma/plugin.rb +6 -12
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +2 -4
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +85 -316
- data/lib/puma/request.rb +467 -0
- data/lib/puma/runner.rb +31 -52
- data/lib/puma/server.rb +275 -726
- data/lib/puma/single.rb +11 -67
- data/lib/puma/state_file.rb +8 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +129 -81
- data/lib/puma/util.rb +13 -6
- data/lib/rack/handler/puma.rb +5 -6
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +45 -28
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- 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/minissl.rb
CHANGED
@@ -2,11 +2,21 @@
|
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'io/wait'
|
5
|
-
|
5
|
+
rescue LoadError
|
6
6
|
end
|
7
7
|
|
8
|
+
# need for Puma::MiniSSL::OPENSSL constants used in `HAS_TLS1_3`
|
9
|
+
require 'puma/puma_http11'
|
10
|
+
|
8
11
|
module Puma
|
9
12
|
module MiniSSL
|
13
|
+
# Define constant at runtime, as it's easy to determine at built time,
|
14
|
+
# but Puma could (it shouldn't) be loaded with an older OpenSSL version
|
15
|
+
# @version 5.0.0
|
16
|
+
HAS_TLS1_3 = !IS_JRUBY &&
|
17
|
+
(OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
|
18
|
+
(OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1
|
19
|
+
|
10
20
|
class Socket
|
11
21
|
def initialize(socket, engine)
|
12
22
|
@socket = socket
|
@@ -14,6 +24,7 @@ module Puma
|
|
14
24
|
@peercert = nil
|
15
25
|
end
|
16
26
|
|
27
|
+
# @!attribute [r] to_io
|
17
28
|
def to_io
|
18
29
|
@socket
|
19
30
|
end
|
@@ -22,6 +33,27 @@ module Puma
|
|
22
33
|
@socket.closed?
|
23
34
|
end
|
24
35
|
|
36
|
+
# Returns a two element array,
|
37
|
+
# first is protocol version (SSL_get_version),
|
38
|
+
# second is 'handshake' state (SSL_state_string)
|
39
|
+
#
|
40
|
+
# Used for dropping tcp connections to ssl.
|
41
|
+
# See OpenSSL ssl/ssl_stat.c SSL_state_string for info
|
42
|
+
# @!attribute [r] ssl_version_state
|
43
|
+
# @version 5.0.0
|
44
|
+
#
|
45
|
+
def ssl_version_state
|
46
|
+
IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
|
47
|
+
end
|
48
|
+
|
49
|
+
# Used to check the handshake status, in particular when a TCP connection
|
50
|
+
# is made with TLSv1.3 as an available protocol
|
51
|
+
# @version 5.0.0
|
52
|
+
def bad_tlsv1_3?
|
53
|
+
HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
|
54
|
+
end
|
55
|
+
private :bad_tlsv1_3?
|
56
|
+
|
25
57
|
def readpartial(size)
|
26
58
|
while true
|
27
59
|
output = @engine.read
|
@@ -54,22 +86,22 @@ module Puma
|
|
54
86
|
output = engine_read_all
|
55
87
|
return output if output
|
56
88
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
89
|
+
data = @socket.read_nonblock(size, exception: false)
|
90
|
+
if data == :wait_readable || data == :wait_writable
|
91
|
+
# It would make more sense to let @socket.read_nonblock raise
|
92
|
+
# EAGAIN if necessary but it seems like it'll misbehave on Windows.
|
93
|
+
# I don't have a Windows machine to debug this so I can't explain
|
94
|
+
# exactly whats happening in that OS. Please let me know if you
|
95
|
+
# find out!
|
96
|
+
#
|
97
|
+
# In the meantime, we can emulate the correct behavior by
|
98
|
+
# capturing :wait_readable & :wait_writable and raising EAGAIN
|
99
|
+
# ourselves.
|
100
|
+
raise IO::EAGAINWaitReadable
|
101
|
+
elsif data.nil?
|
102
|
+
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
|
103
|
+
return nil
|
104
|
+
end
|
73
105
|
|
74
106
|
@engine.inject(data)
|
75
107
|
output = engine_read_all
|
@@ -85,22 +117,23 @@ module Puma
|
|
85
117
|
def write(data)
|
86
118
|
return 0 if data.empty?
|
87
119
|
|
88
|
-
|
120
|
+
data_size = data.bytesize
|
121
|
+
need = data_size
|
89
122
|
|
90
123
|
while true
|
91
124
|
wrote = @engine.write data
|
92
|
-
enc = @engine.extract
|
93
125
|
|
94
|
-
|
95
|
-
|
96
|
-
|
126
|
+
enc_wr = ''.dup
|
127
|
+
while (enc = @engine.extract)
|
128
|
+
enc_wr << enc
|
97
129
|
end
|
130
|
+
@socket.write enc_wr unless enc_wr.empty?
|
98
131
|
|
99
132
|
need -= wrote
|
100
133
|
|
101
|
-
return
|
134
|
+
return data_size if need == 0
|
102
135
|
|
103
|
-
data = data
|
136
|
+
data = data.byteslice(wrote..-1)
|
104
137
|
end
|
105
138
|
end
|
106
139
|
|
@@ -108,14 +141,18 @@ module Puma
|
|
108
141
|
alias_method :<<, :write
|
109
142
|
|
110
143
|
# This is a temporary fix to deal with websockets code using
|
111
|
-
# write_nonblock.
|
144
|
+
# write_nonblock.
|
145
|
+
|
146
|
+
# The problem with implementing it properly
|
112
147
|
# is that it means we'd have to have the ability to rewind
|
113
148
|
# an engine because after we write+extract, the socket
|
114
149
|
# write_nonblock call might raise an exception and later
|
115
150
|
# code would pass the same data in, but the engine would think
|
116
|
-
# it had already written the data in.
|
117
|
-
#
|
118
|
-
#
|
151
|
+
# it had already written the data in.
|
152
|
+
#
|
153
|
+
# So for the time being (and since write blocking is quite rare),
|
154
|
+
# go ahead and actually block in write_nonblock.
|
155
|
+
#
|
119
156
|
def write_nonblock(data, *_)
|
120
157
|
write data
|
121
158
|
end
|
@@ -126,11 +163,14 @@ module Puma
|
|
126
163
|
|
127
164
|
def read_and_drop(timeout = 1)
|
128
165
|
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
166
|
+
case @socket.read_nonblock(1024, exception: false)
|
167
|
+
when nil
|
168
|
+
:eof
|
169
|
+
when :wait_readable
|
170
|
+
:eagain
|
171
|
+
else
|
172
|
+
:drop
|
173
|
+
end
|
134
174
|
end
|
135
175
|
|
136
176
|
def should_drop_bytes?
|
@@ -142,9 +182,7 @@ module Puma
|
|
142
182
|
# Read any drop any partially initialized sockets and any received bytes during shutdown.
|
143
183
|
# Don't let this socket hold this loop forever.
|
144
184
|
# If it can't send more packets within 1s, then give up.
|
145
|
-
while should_drop_bytes?
|
146
|
-
return if [:timeout, :eof].include?(read_and_drop(1))
|
147
|
-
end
|
185
|
+
return if [:timeout, :eof].include?(read_and_drop(1)) while should_drop_bytes?
|
148
186
|
rescue IOError, SystemCallError
|
149
187
|
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
150
188
|
# nothing
|
@@ -153,10 +191,12 @@ module Puma
|
|
153
191
|
end
|
154
192
|
end
|
155
193
|
|
194
|
+
# @!attribute [r] peeraddr
|
156
195
|
def peeraddr
|
157
196
|
@socket.peeraddr
|
158
197
|
end
|
159
198
|
|
199
|
+
# @!attribute [r] peercert
|
160
200
|
def peercert
|
161
201
|
return @peercert if @peercert
|
162
202
|
|
@@ -167,18 +207,25 @@ module Puma
|
|
167
207
|
end
|
168
208
|
end
|
169
209
|
|
170
|
-
if
|
210
|
+
if IS_JRUBY
|
211
|
+
OPENSSL_NO_SSL3 = false
|
212
|
+
OPENSSL_NO_TLS1 = false
|
213
|
+
|
171
214
|
class SSLError < StandardError
|
172
215
|
# Define this for jruby even though it isn't used.
|
173
216
|
end
|
174
|
-
|
175
|
-
def self.check; end
|
176
217
|
end
|
177
218
|
|
178
219
|
class Context
|
179
220
|
attr_accessor :verify_mode
|
221
|
+
attr_reader :no_tlsv1, :no_tlsv1_1
|
222
|
+
|
223
|
+
def initialize
|
224
|
+
@no_tlsv1 = false
|
225
|
+
@no_tlsv1_1 = false
|
226
|
+
end
|
180
227
|
|
181
|
-
if
|
228
|
+
if IS_JRUBY
|
182
229
|
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
|
183
230
|
attr_reader :keystore
|
184
231
|
attr_accessor :keystore_pass
|
@@ -199,6 +246,7 @@ module Puma
|
|
199
246
|
attr_reader :cert
|
200
247
|
attr_reader :ca
|
201
248
|
attr_accessor :ssl_cipher_filter
|
249
|
+
attr_accessor :verification_flags
|
202
250
|
|
203
251
|
def key=(key)
|
204
252
|
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
@@ -220,41 +268,92 @@ module Puma
|
|
220
268
|
raise "Cert not configured" unless @cert
|
221
269
|
end
|
222
270
|
end
|
271
|
+
|
272
|
+
# disables TLSv1
|
273
|
+
# @!attribute [w] no_tlsv1=
|
274
|
+
def no_tlsv1=(tlsv1)
|
275
|
+
raise ArgumentError, "Invalid value of no_tlsv1=" unless ['true', 'false', true, false].include?(tlsv1)
|
276
|
+
@no_tlsv1 = tlsv1
|
277
|
+
end
|
278
|
+
|
279
|
+
# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
|
280
|
+
# @!attribute [w] no_tlsv1_1=
|
281
|
+
def no_tlsv1_1=(tlsv1_1)
|
282
|
+
raise ArgumentError, "Invalid value of no_tlsv1_1=" unless ['true', 'false', true, false].include?(tlsv1_1)
|
283
|
+
@no_tlsv1_1 = tlsv1_1
|
284
|
+
end
|
285
|
+
|
223
286
|
end
|
224
287
|
|
225
288
|
VERIFY_NONE = 0
|
226
289
|
VERIFY_PEER = 1
|
227
290
|
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
228
291
|
|
292
|
+
# https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
|
293
|
+
# /* Certificate verify flags */
|
294
|
+
VERIFICATION_FLAGS = {
|
295
|
+
"USE_CHECK_TIME" => 0x2,
|
296
|
+
"CRL_CHECK" => 0x4,
|
297
|
+
"CRL_CHECK_ALL" => 0x8,
|
298
|
+
"IGNORE_CRITICAL" => 0x10,
|
299
|
+
"X509_STRICT" => 0x20,
|
300
|
+
"ALLOW_PROXY_CERTS" => 0x40,
|
301
|
+
"POLICY_CHECK" => 0x80,
|
302
|
+
"EXPLICIT_POLICY" => 0x100,
|
303
|
+
"INHIBIT_ANY" => 0x200,
|
304
|
+
"INHIBIT_MAP" => 0x400,
|
305
|
+
"NOTIFY_POLICY" => 0x800,
|
306
|
+
"EXTENDED_CRL_SUPPORT" => 0x1000,
|
307
|
+
"USE_DELTAS" => 0x2000,
|
308
|
+
"CHECK_SS_SIGNATURE" => 0x4000,
|
309
|
+
"TRUSTED_FIRST" => 0x8000,
|
310
|
+
"SUITEB_128_LOS_ONLY" => 0x10000,
|
311
|
+
"SUITEB_192_LOS" => 0x20000,
|
312
|
+
"SUITEB_128_LOS" => 0x30000,
|
313
|
+
"PARTIAL_CHAIN" => 0x80000,
|
314
|
+
"NO_ALT_CHAINS" => 0x100000,
|
315
|
+
"NO_CHECK_TIME" => 0x200000
|
316
|
+
}.freeze
|
317
|
+
|
229
318
|
class Server
|
230
319
|
def initialize(socket, ctx)
|
231
320
|
@socket = socket
|
232
321
|
@ctx = ctx
|
233
|
-
|
234
|
-
|
235
|
-
def to_io
|
236
|
-
@socket
|
322
|
+
@eng_ctx = IS_JRUBY ? @ctx : SSLContext.new(ctx)
|
237
323
|
end
|
238
324
|
|
239
325
|
def accept
|
240
326
|
@ctx.check
|
241
327
|
io = @socket.accept
|
242
|
-
engine = Engine.server @
|
243
|
-
|
328
|
+
engine = Engine.server @eng_ctx
|
244
329
|
Socket.new io, engine
|
245
330
|
end
|
246
331
|
|
247
332
|
def accept_nonblock
|
248
333
|
@ctx.check
|
249
334
|
io = @socket.accept_nonblock
|
250
|
-
engine = Engine.server @
|
251
|
-
|
335
|
+
engine = Engine.server @eng_ctx
|
252
336
|
Socket.new io, engine
|
253
337
|
end
|
254
338
|
|
339
|
+
# @!attribute [r] to_io
|
340
|
+
def to_io
|
341
|
+
@socket
|
342
|
+
end
|
343
|
+
|
344
|
+
# @!attribute [r] addr
|
345
|
+
# @version 5.0.0
|
346
|
+
def addr
|
347
|
+
@socket.addr
|
348
|
+
end
|
349
|
+
|
255
350
|
def close
|
256
351
|
@socket.close unless @socket.closed? # closed? call is for Windows
|
257
352
|
end
|
353
|
+
|
354
|
+
def closed?
|
355
|
+
@socket.closed?
|
356
|
+
end
|
258
357
|
end
|
259
358
|
end
|
260
359
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Puma
|
2
|
+
module MiniSSL
|
3
|
+
class ContextBuilder
|
4
|
+
def initialize(params, events)
|
5
|
+
@params = params
|
6
|
+
@events = events
|
7
|
+
end
|
8
|
+
|
9
|
+
def context
|
10
|
+
ctx = MiniSSL::Context.new
|
11
|
+
|
12
|
+
if defined?(JRUBY_VERSION)
|
13
|
+
unless params['keystore']
|
14
|
+
events.error "Please specify the Java keystore via 'keystore='"
|
15
|
+
end
|
16
|
+
|
17
|
+
ctx.keystore = params['keystore']
|
18
|
+
|
19
|
+
unless params['keystore-pass']
|
20
|
+
events.error "Please specify the Java keystore password via 'keystore-pass='"
|
21
|
+
end
|
22
|
+
|
23
|
+
ctx.keystore_pass = params['keystore-pass']
|
24
|
+
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
25
|
+
else
|
26
|
+
unless params['key']
|
27
|
+
events.error "Please specify the SSL key via 'key='"
|
28
|
+
end
|
29
|
+
|
30
|
+
ctx.key = params['key']
|
31
|
+
|
32
|
+
unless params['cert']
|
33
|
+
events.error "Please specify the SSL cert via 'cert='"
|
34
|
+
end
|
35
|
+
|
36
|
+
ctx.cert = params['cert']
|
37
|
+
|
38
|
+
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
39
|
+
unless params['ca']
|
40
|
+
events.error "Please specify the SSL ca via 'ca='"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ctx.ca = params['ca'] if params['ca']
|
45
|
+
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
46
|
+
end
|
47
|
+
|
48
|
+
ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
|
49
|
+
ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'
|
50
|
+
|
51
|
+
if params['verify_mode']
|
52
|
+
ctx.verify_mode = case params['verify_mode']
|
53
|
+
when "peer"
|
54
|
+
MiniSSL::VERIFY_PEER
|
55
|
+
when "force_peer"
|
56
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
57
|
+
when "none"
|
58
|
+
MiniSSL::VERIFY_NONE
|
59
|
+
else
|
60
|
+
events.error "Please specify a valid verify_mode="
|
61
|
+
MiniSSL::VERIFY_NONE
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if params['verification_flags']
|
66
|
+
ctx.verification_flags = params['verification_flags'].split(',').
|
67
|
+
map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
|
68
|
+
inject { |sum, flag| sum ? sum | flag : flag }
|
69
|
+
end
|
70
|
+
|
71
|
+
ctx
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_reader :params, :events
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/puma/null_io.rb
CHANGED
@@ -9,13 +9,17 @@ module Puma
|
|
9
9
|
nil
|
10
10
|
end
|
11
11
|
|
12
|
+
def string
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
12
16
|
def each
|
13
17
|
end
|
14
18
|
|
15
19
|
# Mimics IO#read with no data.
|
16
20
|
#
|
17
21
|
def read(count = nil, _buffer = nil)
|
18
|
-
|
22
|
+
count && count > 0 ? nil : ""
|
19
23
|
end
|
20
24
|
|
21
25
|
def rewind
|
@@ -32,6 +36,10 @@ module Puma
|
|
32
36
|
true
|
33
37
|
end
|
34
38
|
|
39
|
+
def sync
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
35
43
|
def sync=(v)
|
36
44
|
end
|
37
45
|
|
@@ -40,5 +48,9 @@ module Puma
|
|
40
48
|
|
41
49
|
def write(*ary)
|
42
50
|
end
|
51
|
+
|
52
|
+
def flush
|
53
|
+
self
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
data/lib/puma/plugin.rb
CHANGED
@@ -10,7 +10,7 @@ module Puma
|
|
10
10
|
|
11
11
|
def create(name)
|
12
12
|
if cls = Plugins.find(name)
|
13
|
-
plugin = cls.new
|
13
|
+
plugin = cls.new
|
14
14
|
@instances << plugin
|
15
15
|
return plugin
|
16
16
|
end
|
@@ -62,8 +62,11 @@ module Puma
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def fire_background
|
65
|
-
@background.
|
66
|
-
Thread.new
|
65
|
+
@background.each_with_index do |b, i|
|
66
|
+
Thread.new do
|
67
|
+
Puma.set_thread_name "plugin background #{i}"
|
68
|
+
b.call
|
69
|
+
end
|
67
70
|
end
|
68
71
|
end
|
69
72
|
end
|
@@ -101,17 +104,8 @@ module Puma
|
|
101
104
|
Plugins.register name, cls
|
102
105
|
end
|
103
106
|
|
104
|
-
def initialize(loader)
|
105
|
-
@loader = loader
|
106
|
-
end
|
107
|
-
|
108
107
|
def in_background(&blk)
|
109
108
|
Plugins.add_background blk
|
110
109
|
end
|
111
|
-
|
112
|
-
def workers_supported?
|
113
|
-
return false if Puma.jruby? || Puma.windows?
|
114
|
-
true
|
115
|
-
end
|
116
110
|
end
|
117
111
|
end
|