puma 5.5.2 → 6.3.0
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 +336 -3
- data/README.md +61 -16
- data/bin/puma-wild +1 -1
- data/docs/architecture.md +4 -4
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/nginx.md +1 -1
- data/docs/signals.md +1 -0
- data/docs/systemd.md +1 -2
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +28 -14
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +135 -23
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +188 -102
- data/ext/puma_http11/puma_http11.c +18 -10
- data/lib/puma/app/status.rb +7 -4
- data/lib/puma/binder.rb +62 -51
- data/lib/puma/cli.rb +19 -20
- data/lib/puma/client.rb +108 -26
- data/lib/puma/cluster/worker.rb +23 -16
- data/lib/puma/cluster/worker_handle.rb +8 -1
- data/lib/puma/cluster.rb +62 -41
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +76 -55
- data/lib/puma/const.rb +133 -97
- data/lib/puma/control_cli.rb +21 -18
- data/lib/puma/detect.rb +12 -2
- data/lib/puma/dsl.rb +270 -55
- data/lib/puma/error_logger.rb +18 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +114 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +30 -16
- data/lib/puma/minissl.rb +126 -17
- data/lib/puma/null_io.rb +5 -0
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +1 -1
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +365 -161
- data/lib/puma/runner.rb +55 -22
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +91 -94
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +39 -7
- data/lib/puma/thread_pool.rb +25 -21
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +12 -11
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +1 -1
- metadata +11 -6
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
data/lib/puma/const.rb
CHANGED
@@ -5,7 +5,6 @@ module Puma
|
|
5
5
|
class UnsupportedOption < RuntimeError
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
8
|
# Every standard HTTP code mapped to the appropriate message. These are
|
10
9
|
# used so frequently that they are placed directly in Puma for easy
|
11
10
|
# access rather than Puma::Const itself.
|
@@ -19,6 +18,7 @@ module Puma
|
|
19
18
|
100 => 'Continue',
|
20
19
|
101 => 'Switching Protocols',
|
21
20
|
102 => 'Processing',
|
21
|
+
103 => 'Early Hints',
|
22
22
|
200 => 'OK',
|
23
23
|
201 => 'Created',
|
24
24
|
202 => 'Accepted',
|
@@ -50,16 +50,16 @@ module Puma
|
|
50
50
|
410 => 'Gone',
|
51
51
|
411 => 'Length Required',
|
52
52
|
412 => 'Precondition Failed',
|
53
|
-
413 => '
|
53
|
+
413 => 'Content Too Large',
|
54
54
|
414 => 'URI Too Long',
|
55
55
|
415 => 'Unsupported Media Type',
|
56
56
|
416 => 'Range Not Satisfiable',
|
57
57
|
417 => 'Expectation Failed',
|
58
|
-
418 => 'I\'m A Teapot',
|
59
58
|
421 => 'Misdirected Request',
|
60
|
-
422 => 'Unprocessable
|
59
|
+
422 => 'Unprocessable Content',
|
61
60
|
423 => 'Locked',
|
62
61
|
424 => 'Failed Dependency',
|
62
|
+
425 => 'Too Early',
|
63
63
|
426 => 'Upgrade Required',
|
64
64
|
428 => 'Precondition Required',
|
65
65
|
429 => 'Too Many Requests',
|
@@ -74,9 +74,9 @@ module Puma
|
|
74
74
|
506 => 'Variant Also Negotiates',
|
75
75
|
507 => 'Insufficient Storage',
|
76
76
|
508 => 'Loop Detected',
|
77
|
-
510 => 'Not Extended',
|
77
|
+
510 => 'Not Extended (OBSOLETED)',
|
78
78
|
511 => 'Network Authentication Required'
|
79
|
-
}
|
79
|
+
}.freeze
|
80
80
|
|
81
81
|
# For some HTTP status codes the client only expects headers.
|
82
82
|
#
|
@@ -85,7 +85,7 @@ module Puma
|
|
85
85
|
204 => true,
|
86
86
|
205 => true,
|
87
87
|
304 => true
|
88
|
-
}
|
88
|
+
}.freeze
|
89
89
|
|
90
90
|
# Frequently used constants when constructing requests or responses. Many times
|
91
91
|
# the constant just refers to a string with the same contents. Using these constants
|
@@ -100,54 +100,41 @@ 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 = "6.3.0"
|
104
|
+
CODE_NAME = "Mugi No Toki Itaru"
|
105
105
|
|
106
|
-
PUMA_SERVER_STRING = [
|
106
|
+
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
107
107
|
|
108
108
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
109
109
|
|
110
|
-
# The default number of seconds for another request within a persistent
|
111
|
-
# session.
|
112
|
-
PERSISTENT_TIMEOUT = 20
|
113
|
-
|
114
|
-
# The default number of seconds to wait until we get the first data
|
115
|
-
# for the request
|
116
|
-
FIRST_DATA_TIMEOUT = 30
|
117
|
-
|
118
110
|
# How long to wait when getting some write blocking on the socket when
|
119
111
|
# sending data back
|
120
112
|
WRITE_TIMEOUT = 10
|
121
113
|
|
122
|
-
# How many requests to attempt inline before sending a client back to
|
123
|
-
# the reactor to be subject to normal ordering. The idea here is that
|
124
|
-
# we amortize the cost of going back to the reactor for a well behaved
|
125
|
-
# but very "greedy" client across 10 requests. This prevents a not
|
126
|
-
# well behaved client from monopolizing the thread forever.
|
127
|
-
MAX_FAST_INLINE = 10
|
128
|
-
|
129
114
|
# The original URI requested by the client.
|
130
|
-
REQUEST_URI=
|
131
|
-
REQUEST_PATH =
|
132
|
-
QUERY_STRING =
|
133
|
-
CONTENT_LENGTH = "CONTENT_LENGTH"
|
115
|
+
REQUEST_URI= "REQUEST_URI"
|
116
|
+
REQUEST_PATH = "REQUEST_PATH"
|
117
|
+
QUERY_STRING = "QUERY_STRING"
|
118
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
134
119
|
|
135
|
-
PATH_INFO =
|
120
|
+
PATH_INFO = "PATH_INFO"
|
136
121
|
|
137
|
-
PUMA_TMP_BASE = "puma"
|
122
|
+
PUMA_TMP_BASE = "puma"
|
138
123
|
|
139
124
|
ERROR_RESPONSE = {
|
140
125
|
# Indicate that we couldn't parse the request
|
141
|
-
400 => "HTTP/1.1 400 Bad Request\r\n\r\n"
|
126
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
142
127
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
143
|
-
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\
|
128
|
+
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n",
|
144
129
|
# The standard empty 408 response for requests that timed out.
|
145
|
-
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\
|
130
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n",
|
146
131
|
# Indicate that there was an internal error, obviously.
|
147
|
-
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
132
|
+
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
|
133
|
+
# Incorrect or invalid header value
|
134
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
|
148
135
|
# A common header for indicating the server is too busy. Not used yet.
|
149
|
-
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\
|
150
|
-
}
|
136
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\n"
|
137
|
+
}.freeze
|
151
138
|
|
152
139
|
# The basic max request size we'll try to read.
|
153
140
|
CHUNK_SIZE = 16 * 1024
|
@@ -159,87 +146,136 @@ module Puma
|
|
159
146
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
160
147
|
MAX_BODY = MAX_HEADER
|
161
148
|
|
162
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
163
|
-
HEAD = "HEAD"
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
149
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
150
|
+
HEAD = "HEAD"
|
151
|
+
|
152
|
+
# based on https://www.rfc-editor.org/rfc/rfc9110.html#name-overview,
|
153
|
+
# with CONNECT removed, and PATCH added
|
154
|
+
SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
|
155
|
+
|
156
|
+
# list from https://www.iana.org/assignments/http-methods/http-methods.xhtml
|
157
|
+
# as of 04-May-23
|
158
|
+
IANA_HTTP_METHODS = %w[
|
159
|
+
ACL
|
160
|
+
BASELINE-CONTROL
|
161
|
+
BIND
|
162
|
+
CHECKIN
|
163
|
+
CHECKOUT
|
164
|
+
CONNECT
|
165
|
+
COPY
|
166
|
+
DELETE
|
167
|
+
GET
|
168
|
+
HEAD
|
169
|
+
LABEL
|
170
|
+
LINK
|
171
|
+
LOCK
|
172
|
+
MERGE
|
173
|
+
MKACTIVITY
|
174
|
+
MKCALENDAR
|
175
|
+
MKCOL
|
176
|
+
MKREDIRECTREF
|
177
|
+
MKWORKSPACE
|
178
|
+
MOVE
|
179
|
+
OPTIONS
|
180
|
+
ORDERPATCH
|
181
|
+
PATCH
|
182
|
+
POST
|
183
|
+
PRI
|
184
|
+
PROPFIND
|
185
|
+
PROPPATCH
|
186
|
+
PUT
|
187
|
+
REBIND
|
188
|
+
REPORT
|
189
|
+
SEARCH
|
190
|
+
TRACE
|
191
|
+
UNBIND
|
192
|
+
UNCHECKOUT
|
193
|
+
UNLINK
|
194
|
+
UNLOCK
|
195
|
+
UPDATE
|
196
|
+
UPDATEREDIRECTREF
|
197
|
+
VERSION-CONTROL
|
198
|
+
].freeze
|
171
199
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
200
|
+
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
201
|
+
LINE_END = "\r\n"
|
202
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
203
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
204
|
+
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
205
|
+
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
206
|
+
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
179
207
|
|
180
|
-
|
181
|
-
|
208
|
+
SERVER_NAME = "SERVER_NAME"
|
209
|
+
SERVER_PORT = "SERVER_PORT"
|
210
|
+
HTTP_HOST = "HTTP_HOST"
|
211
|
+
PORT_80 = "80"
|
212
|
+
PORT_443 = "443"
|
213
|
+
LOCALHOST = "localhost"
|
214
|
+
LOCALHOST_IPV4 = "127.0.0.1"
|
215
|
+
LOCALHOST_IPV6 = "::1"
|
216
|
+
UNSPECIFIED_IPV4 = "0.0.0.0"
|
217
|
+
UNSPECIFIED_IPV6 = "::"
|
182
218
|
|
183
|
-
|
184
|
-
|
185
|
-
CGI_VER = "CGI/1.2".freeze
|
219
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
220
|
+
HTTP_11 = "HTTP/1.1"
|
186
221
|
|
187
|
-
|
188
|
-
|
189
|
-
|
222
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
223
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
224
|
+
CGI_VER = "CGI/1.2"
|
190
225
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
PUMA_SOCKET = "puma.socket".freeze
|
195
|
-
PUMA_CONFIG = "puma.config".freeze
|
196
|
-
PUMA_PEERCERT = "puma.peercert".freeze
|
226
|
+
STOP_COMMAND = "?"
|
227
|
+
HALT_COMMAND = "!"
|
228
|
+
RESTART_COMMAND = "R"
|
197
229
|
|
198
|
-
|
199
|
-
|
230
|
+
RACK_INPUT = "rack.input"
|
231
|
+
RACK_URL_SCHEME = "rack.url_scheme"
|
232
|
+
RACK_AFTER_REPLY = "rack.after_reply"
|
233
|
+
PUMA_SOCKET = "puma.socket"
|
234
|
+
PUMA_CONFIG = "puma.config"
|
235
|
+
PUMA_PEERCERT = "puma.peercert"
|
200
236
|
|
201
|
-
|
237
|
+
HTTP = "http"
|
238
|
+
HTTPS = "https"
|
202
239
|
|
203
|
-
|
204
|
-
HTTP_CONNECTION = "HTTP_CONNECTION".freeze
|
205
|
-
HTTP_EXPECT = "HTTP_EXPECT".freeze
|
206
|
-
CONTINUE = "100-continue".freeze
|
240
|
+
HTTPS_KEY = "HTTPS"
|
207
241
|
|
208
|
-
|
209
|
-
|
210
|
-
|
242
|
+
HTTP_VERSION = "HTTP_VERSION"
|
243
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
244
|
+
HTTP_EXPECT = "HTTP_EXPECT"
|
245
|
+
CONTINUE = "100-continue"
|
211
246
|
|
212
|
-
|
213
|
-
|
247
|
+
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
248
|
+
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
249
|
+
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
214
250
|
|
215
|
-
|
216
|
-
|
217
|
-
TRANSFER_ENCODING = "transfer-encoding".freeze
|
218
|
-
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
|
251
|
+
CLOSE = "close"
|
252
|
+
KEEP_ALIVE = "keep-alive"
|
219
253
|
|
220
|
-
|
221
|
-
|
254
|
+
CONTENT_LENGTH2 = "content-length"
|
255
|
+
CONTENT_LENGTH_S = "Content-Length: "
|
256
|
+
TRANSFER_ENCODING = "transfer-encoding"
|
257
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
222
258
|
|
223
|
-
|
224
|
-
|
259
|
+
CONNECTION_CLOSE = "Connection: close\r\n"
|
260
|
+
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
225
261
|
|
226
|
-
|
262
|
+
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
263
|
+
CLOSE_CHUNKED = "0\r\n\r\n"
|
227
264
|
|
228
|
-
|
265
|
+
CHUNKED = "chunked"
|
229
266
|
|
230
|
-
|
267
|
+
COLON = ": "
|
231
268
|
|
232
|
-
|
233
|
-
HIJACK = "rack.hijack".freeze
|
234
|
-
HIJACK_IO = "rack.hijack_io".freeze
|
269
|
+
NEWLINE = "\n"
|
235
270
|
|
236
|
-
|
271
|
+
HIJACK_P = "rack.hijack?"
|
272
|
+
HIJACK = "rack.hijack"
|
273
|
+
HIJACK_IO = "rack.hijack_io"
|
237
274
|
|
238
|
-
|
239
|
-
WORKER_CHECK_INTERVAL = 5
|
275
|
+
EARLY_HINTS = "rack.early_hints"
|
240
276
|
|
241
277
|
# Illegal character in the key or value of response header
|
242
|
-
DQUOTE = "\""
|
278
|
+
DQUOTE = "\""
|
243
279
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
244
280
|
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
245
281
|
# header values can contain HTAB?
|
data/lib/puma/control_cli.rb
CHANGED
@@ -17,26 +17,27 @@ module Puma
|
|
17
17
|
CMD_PATH_SIG_MAP = {
|
18
18
|
'gc' => nil,
|
19
19
|
'gc-stats' => nil,
|
20
|
-
'halt'
|
21
|
-
'
|
22
|
-
'
|
20
|
+
'halt' => 'SIGQUIT',
|
21
|
+
'info' => 'SIGINFO',
|
22
|
+
'phased-restart' => 'SIGUSR1',
|
23
|
+
'refork' => 'SIGURG',
|
23
24
|
'reload-worker-directory' => nil,
|
24
|
-
'
|
25
|
+
'reopen-log' => 'SIGHUP',
|
26
|
+
'restart' => 'SIGUSR2',
|
25
27
|
'start' => nil,
|
26
28
|
'stats' => nil,
|
27
29
|
'status' => '',
|
28
|
-
'stop'
|
29
|
-
'thread-backtraces' => nil
|
30
|
+
'stop' => 'SIGTERM',
|
31
|
+
'thread-backtraces' => nil,
|
32
|
+
'worker-count-down' => 'SIGTTOU',
|
33
|
+
'worker-count-up' => 'SIGTTIN'
|
30
34
|
}.freeze
|
31
35
|
|
32
|
-
# @deprecated 6.0.0
|
33
|
-
COMMANDS = CMD_PATH_SIG_MAP.keys.freeze
|
34
|
-
|
35
36
|
# commands that cannot be used in a request
|
36
|
-
NO_REQ_COMMANDS = %w
|
37
|
+
NO_REQ_COMMANDS = %w[info reopen-log worker-count-down worker-count-up].freeze
|
37
38
|
|
38
39
|
# @version 5.0.0
|
39
|
-
PRINTABLE_COMMANDS = %w
|
40
|
+
PRINTABLE_COMMANDS = %w[gc-stats stats thread-backtraces].freeze
|
40
41
|
|
41
42
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
42
43
|
@state = nil
|
@@ -185,8 +186,6 @@ module Puma
|
|
185
186
|
|
186
187
|
if @command == 'status'
|
187
188
|
message 'Puma is started'
|
188
|
-
elsif NO_REQ_COMMANDS.include? @command
|
189
|
-
raise "Invalid request command: #{@command}"
|
190
189
|
else
|
191
190
|
url = "/#{@command}"
|
192
191
|
|
@@ -242,7 +241,11 @@ module Puma
|
|
242
241
|
@stdout.flush unless @stdout.sync
|
243
242
|
return
|
244
243
|
elsif sig.start_with? 'SIG'
|
245
|
-
|
244
|
+
if Signal.list.key? sig.sub(/\ASIG/, '')
|
245
|
+
Process.kill sig, @pid
|
246
|
+
else
|
247
|
+
raise "Signal '#{sig}' not available'"
|
248
|
+
end
|
246
249
|
elsif @command == 'status'
|
247
250
|
begin
|
248
251
|
Process.kill 0, @pid
|
@@ -268,7 +271,7 @@ module Puma
|
|
268
271
|
return start if @command == 'start'
|
269
272
|
prepare_configuration
|
270
273
|
|
271
|
-
if Puma.windows? || @control_url
|
274
|
+
if Puma.windows? || @control_url && !NO_REQ_COMMANDS.include?(@command)
|
272
275
|
send_request
|
273
276
|
else
|
274
277
|
send_signal
|
@@ -281,7 +284,7 @@ module Puma
|
|
281
284
|
|
282
285
|
private
|
283
286
|
def start
|
284
|
-
|
287
|
+
require_relative 'cli'
|
285
288
|
|
286
289
|
run_args = []
|
287
290
|
|
@@ -293,13 +296,13 @@ module Puma
|
|
293
296
|
run_args += ["-C", @config_file] if @config_file
|
294
297
|
run_args += ["-e", @environment] if @environment
|
295
298
|
|
296
|
-
|
299
|
+
log_writer = Puma::LogWriter.new(@stdout, @stderr)
|
297
300
|
|
298
301
|
# replace $0 because puma use it to generate restart command
|
299
302
|
puma_cmd = $0.gsub(/pumactl$/, 'puma')
|
300
303
|
$0 = puma_cmd if File.exist?(puma_cmd)
|
301
304
|
|
302
|
-
cli = Puma::CLI.new run_args,
|
305
|
+
cli = Puma::CLI.new run_args, log_writer
|
303
306
|
cli.run
|
304
307
|
end
|
305
308
|
end
|
data/lib/puma/detect.rb
CHANGED
@@ -8,10 +8,16 @@ module Puma
|
|
8
8
|
# @version 5.2.1
|
9
9
|
HAS_FORK = ::Process.respond_to? :fork
|
10
10
|
|
11
|
+
HAS_NATIVE_IO_WAIT = ::IO.public_instance_methods(false).include? :wait_readable
|
12
|
+
|
11
13
|
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
IS_OSX = RUBY_PLATFORM.include? 'darwin'
|
16
|
+
|
17
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
|
18
|
+
IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
|
19
|
+
|
20
|
+
IS_LINUX = !(IS_OSX || IS_WINDOWS)
|
15
21
|
|
16
22
|
# @version 5.2.0
|
17
23
|
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
@@ -20,6 +26,10 @@ module Puma
|
|
20
26
|
IS_JRUBY
|
21
27
|
end
|
22
28
|
|
29
|
+
def self.osx?
|
30
|
+
IS_OSX
|
31
|
+
end
|
32
|
+
|
23
33
|
def self.windows?
|
24
34
|
IS_WINDOWS
|
25
35
|
end
|