puma 2.16.0 → 3.0.0.rc1
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/Manifest.txt +5 -0
- data/README.md +4 -1
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +39 -39
- data/lib/puma.rb +1 -0
- data/lib/puma/app/status.rb +1 -1
- data/lib/puma/binder.rb +6 -1
- data/lib/puma/cli.rb +125 -494
- data/lib/puma/cluster.rb +21 -18
- data/lib/puma/configuration.rb +189 -58
- data/lib/puma/const.rb +2 -2
- data/lib/puma/control_cli.rb +57 -72
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +6 -0
- data/lib/puma/detect.rb +8 -1
- data/lib/puma/dsl.rb +105 -26
- data/lib/puma/events.rb +5 -0
- data/lib/puma/launcher.rb +397 -0
- data/lib/puma/null_io.rb +15 -0
- data/lib/puma/plugin.rb +91 -0
- data/lib/puma/plugin/tmp_restart.rb +23 -0
- data/lib/puma/runner.rb +19 -14
- data/lib/puma/server.rb +1 -0
- data/lib/puma/single.rb +9 -4
- data/lib/puma/state_file.rb +27 -0
- data/lib/rack/handler/puma.rb +26 -27
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec0eeb5886074470b19df49db748d9fad55c57c6
|
4
|
+
data.tar.gz: 74521d8b05a10a149cf6aa0fb4dc4c7e199ab124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d64e58108913abf1b2252ba3038553ec28c82cfe96aa8812de7bdc58215881aea90a1048b490cee8699df99c73f3ea2b9d1dd3b472d082fbcc7974003c79e16c
|
7
|
+
data.tar.gz: 35befe3e0a9d01fa14f58841ecbcef2fa84a99ba8b3c564ceacb99101e52d50a855c7ab65c983caf816a09bf5547fb35b4e6f111985bea1cb5940e46a01b4dc8
|
data/Manifest.txt
CHANGED
@@ -39,6 +39,7 @@ lib/puma/compat.rb
|
|
39
39
|
lib/puma/configuration.rb
|
40
40
|
lib/puma/const.rb
|
41
41
|
lib/puma/control_cli.rb
|
42
|
+
lib/puma/convenient.rb
|
42
43
|
lib/puma/daemon_ext.rb
|
43
44
|
lib/puma/delegation.rb
|
44
45
|
lib/puma/detect.rb
|
@@ -47,8 +48,11 @@ lib/puma/events.rb
|
|
47
48
|
lib/puma/io_buffer.rb
|
48
49
|
lib/puma/java_io_buffer.rb
|
49
50
|
lib/puma/jruby_restart.rb
|
51
|
+
lib/puma/launcher.rb
|
50
52
|
lib/puma/minissl.rb
|
51
53
|
lib/puma/null_io.rb
|
54
|
+
lib/puma/plugin.rb
|
55
|
+
lib/puma/plugin/tmp_restart.rb
|
52
56
|
lib/puma/rack/backports/uri/common_18.rb
|
53
57
|
lib/puma/rack/backports/uri/common_192.rb
|
54
58
|
lib/puma/rack/backports/uri/common_193.rb
|
@@ -59,6 +63,7 @@ lib/puma/reactor.rb
|
|
59
63
|
lib/puma/runner.rb
|
60
64
|
lib/puma/server.rb
|
61
65
|
lib/puma/single.rb
|
66
|
+
lib/puma/state_file.rb
|
62
67
|
lib/puma/tcp_logger.rb
|
63
68
|
lib/puma/thread_pool.rb
|
64
69
|
lib/puma/util.rb
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Puma: A Ruby Web Server Built For Concurrency
|
2
2
|
|
3
|
-
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/puma/puma?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
3
|
+
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/puma/puma?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/puma/puma.svg)](http://travis-ci.org/puma/puma)
|
5
|
+
[![Dependency Status](https://gemnasium.com/puma/puma.svg)](https://gemnasium.com/puma/puma)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/puma/puma.svg)](https://codeclimate.com/github/puma/puma)
|
4
7
|
|
5
8
|
## Description
|
6
9
|
|
@@ -7,8 +7,8 @@ public class Http11Parser {
|
|
7
7
|
/** Machine **/
|
8
8
|
|
9
9
|
%%{
|
10
|
-
|
11
|
-
machine
|
10
|
+
|
11
|
+
machine puma_parser;
|
12
12
|
|
13
13
|
action mark {parser.mark = fpc; }
|
14
14
|
|
@@ -60,7 +60,7 @@ public class Http11Parser {
|
|
60
60
|
fbreak;
|
61
61
|
}
|
62
62
|
|
63
|
-
include
|
63
|
+
include puma_parser_common "http11_parser_common.rl";
|
64
64
|
|
65
65
|
}%%
|
66
66
|
|
@@ -152,10 +152,10 @@ public class Http11Parser {
|
|
152
152
|
}
|
153
153
|
|
154
154
|
public boolean has_error() {
|
155
|
-
return parser.cs ==
|
155
|
+
return parser.cs == puma_parser_error;
|
156
156
|
}
|
157
157
|
|
158
158
|
public boolean is_finished() {
|
159
|
-
return parser.cs ==
|
159
|
+
return parser.cs == puma_parser_first_final;
|
160
160
|
}
|
161
161
|
}
|
@@ -15,7 +15,7 @@ public class Http11Parser {
|
|
15
15
|
/** Data **/
|
16
16
|
|
17
17
|
// line 18 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
18
|
-
private static byte[]
|
18
|
+
private static byte[] init__puma_parser_actions_0()
|
19
19
|
{
|
20
20
|
return new byte [] {
|
21
21
|
0, 1, 0, 1, 2, 1, 3, 1, 4, 1, 5, 1,
|
@@ -25,10 +25,10 @@ private static byte[] init__http_parser_actions_0()
|
|
25
25
|
};
|
26
26
|
}
|
27
27
|
|
28
|
-
private static final byte
|
28
|
+
private static final byte _puma_parser_actions[] = init__puma_parser_actions_0();
|
29
29
|
|
30
30
|
|
31
|
-
private static short[]
|
31
|
+
private static short[] init__puma_parser_key_offsets_0()
|
32
32
|
{
|
33
33
|
return new short [] {
|
34
34
|
0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36,
|
@@ -39,10 +39,10 @@ private static short[] init__http_parser_key_offsets_0()
|
|
39
39
|
};
|
40
40
|
}
|
41
41
|
|
42
|
-
private static final short
|
42
|
+
private static final short _puma_parser_key_offsets[] = init__puma_parser_key_offsets_0();
|
43
43
|
|
44
44
|
|
45
|
-
private static char[]
|
45
|
+
private static char[] init__puma_parser_trans_keys_0()
|
46
46
|
{
|
47
47
|
return new char [] {
|
48
48
|
36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
|
@@ -80,10 +80,10 @@ private static char[] init__http_parser_trans_keys_0()
|
|
80
80
|
};
|
81
81
|
}
|
82
82
|
|
83
|
-
private static final char
|
83
|
+
private static final char _puma_parser_trans_keys[] = init__puma_parser_trans_keys_0();
|
84
84
|
|
85
85
|
|
86
|
-
private static byte[]
|
86
|
+
private static byte[] init__puma_parser_single_lengths_0()
|
87
87
|
{
|
88
88
|
return new byte [] {
|
89
89
|
0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1,
|
@@ -94,10 +94,10 @@ private static byte[] init__http_parser_single_lengths_0()
|
|
94
94
|
};
|
95
95
|
}
|
96
96
|
|
97
|
-
private static final byte
|
97
|
+
private static final byte _puma_parser_single_lengths[] = init__puma_parser_single_lengths_0();
|
98
98
|
|
99
99
|
|
100
|
-
private static byte[]
|
100
|
+
private static byte[] init__puma_parser_range_lengths_0()
|
101
101
|
{
|
102
102
|
return new byte [] {
|
103
103
|
0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1,
|
@@ -108,10 +108,10 @@ private static byte[] init__http_parser_range_lengths_0()
|
|
108
108
|
};
|
109
109
|
}
|
110
110
|
|
111
|
-
private static final byte
|
111
|
+
private static final byte _puma_parser_range_lengths[] = init__puma_parser_range_lengths_0();
|
112
112
|
|
113
113
|
|
114
|
-
private static short[]
|
114
|
+
private static short[] init__puma_parser_index_offsets_0()
|
115
115
|
{
|
116
116
|
return new short [] {
|
117
117
|
0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36,
|
@@ -122,10 +122,10 @@ private static short[] init__http_parser_index_offsets_0()
|
|
122
122
|
};
|
123
123
|
}
|
124
124
|
|
125
|
-
private static final short
|
125
|
+
private static final short _puma_parser_index_offsets[] = init__puma_parser_index_offsets_0();
|
126
126
|
|
127
127
|
|
128
|
-
private static byte[]
|
128
|
+
private static byte[] init__puma_parser_indicies_0()
|
129
129
|
{
|
130
130
|
return new byte [] {
|
131
131
|
0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3,
|
@@ -158,10 +158,10 @@ private static byte[] init__http_parser_indicies_0()
|
|
158
158
|
};
|
159
159
|
}
|
160
160
|
|
161
|
-
private static final byte
|
161
|
+
private static final byte _puma_parser_indicies[] = init__puma_parser_indicies_0();
|
162
162
|
|
163
163
|
|
164
|
-
private static byte[]
|
164
|
+
private static byte[] init__puma_parser_trans_targs_0()
|
165
165
|
{
|
166
166
|
return new byte [] {
|
167
167
|
2, 0, 3, 38, 4, 24, 28, 25, 5, 20, 6, 7,
|
@@ -174,10 +174,10 @@ private static byte[] init__http_parser_trans_targs_0()
|
|
174
174
|
};
|
175
175
|
}
|
176
176
|
|
177
|
-
private static final byte
|
177
|
+
private static final byte _puma_parser_trans_targs[] = init__puma_parser_trans_targs_0();
|
178
178
|
|
179
179
|
|
180
|
-
private static byte[]
|
180
|
+
private static byte[] init__puma_parser_trans_actions_0()
|
181
181
|
{
|
182
182
|
return new byte [] {
|
183
183
|
1, 0, 11, 0, 1, 1, 1, 1, 13, 13, 1, 0,
|
@@ -190,14 +190,14 @@ private static byte[] init__http_parser_trans_actions_0()
|
|
190
190
|
};
|
191
191
|
}
|
192
192
|
|
193
|
-
private static final byte
|
193
|
+
private static final byte _puma_parser_trans_actions[] = init__puma_parser_trans_actions_0();
|
194
194
|
|
195
195
|
|
196
|
-
static final int
|
197
|
-
static final int
|
198
|
-
static final int
|
196
|
+
static final int puma_parser_start = 1;
|
197
|
+
static final int puma_parser_first_final = 57;
|
198
|
+
static final int puma_parser_error = 0;
|
199
199
|
|
200
|
-
static final int
|
200
|
+
static final int puma_parser_en_main = 1;
|
201
201
|
|
202
202
|
|
203
203
|
// line 69 "ext/puma_http11/http11_parser.java.rl"
|
@@ -238,7 +238,7 @@ static final int http_parser_en_main = 1;
|
|
238
238
|
|
239
239
|
// line 240 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
240
240
|
{
|
241
|
-
cs =
|
241
|
+
cs = puma_parser_start;
|
242
242
|
}
|
243
243
|
|
244
244
|
// line 104 "ext/puma_http11/http11_parser.java.rl"
|
@@ -290,9 +290,9 @@ static final int http_parser_en_main = 1;
|
|
290
290
|
}
|
291
291
|
case 1:
|
292
292
|
_match: do {
|
293
|
-
_keys =
|
294
|
-
_trans =
|
295
|
-
_klen =
|
293
|
+
_keys = _puma_parser_key_offsets[cs];
|
294
|
+
_trans = _puma_parser_index_offsets[cs];
|
295
|
+
_klen = _puma_parser_single_lengths[cs];
|
296
296
|
if ( _klen > 0 ) {
|
297
297
|
int _lower = _keys;
|
298
298
|
int _mid;
|
@@ -302,9 +302,9 @@ case 1:
|
|
302
302
|
break;
|
303
303
|
|
304
304
|
_mid = _lower + ((_upper-_lower) >> 1);
|
305
|
-
if ( data[p] <
|
305
|
+
if ( data[p] < _puma_parser_trans_keys[_mid] )
|
306
306
|
_upper = _mid - 1;
|
307
|
-
else if ( data[p] >
|
307
|
+
else if ( data[p] > _puma_parser_trans_keys[_mid] )
|
308
308
|
_lower = _mid + 1;
|
309
309
|
else {
|
310
310
|
_trans += (_mid - _keys);
|
@@ -315,7 +315,7 @@ case 1:
|
|
315
315
|
_trans += _klen;
|
316
316
|
}
|
317
317
|
|
318
|
-
_klen =
|
318
|
+
_klen = _puma_parser_range_lengths[cs];
|
319
319
|
if ( _klen > 0 ) {
|
320
320
|
int _lower = _keys;
|
321
321
|
int _mid;
|
@@ -325,9 +325,9 @@ case 1:
|
|
325
325
|
break;
|
326
326
|
|
327
327
|
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
|
328
|
-
if ( data[p] <
|
328
|
+
if ( data[p] < _puma_parser_trans_keys[_mid] )
|
329
329
|
_upper = _mid - 2;
|
330
|
-
else if ( data[p] >
|
330
|
+
else if ( data[p] > _puma_parser_trans_keys[_mid+1] )
|
331
331
|
_lower = _mid + 2;
|
332
332
|
else {
|
333
333
|
_trans += ((_mid - _keys)>>1);
|
@@ -338,15 +338,15 @@ case 1:
|
|
338
338
|
}
|
339
339
|
} while (false);
|
340
340
|
|
341
|
-
_trans =
|
342
|
-
cs =
|
341
|
+
_trans = _puma_parser_indicies[_trans];
|
342
|
+
cs = _puma_parser_trans_targs[_trans];
|
343
343
|
|
344
|
-
if (
|
345
|
-
_acts =
|
346
|
-
_nacts = (int)
|
344
|
+
if ( _puma_parser_trans_actions[_trans] != 0 ) {
|
345
|
+
_acts = _puma_parser_trans_actions[_trans];
|
346
|
+
_nacts = (int) _puma_parser_actions[_acts++];
|
347
347
|
while ( _nacts-- > 0 )
|
348
348
|
{
|
349
|
-
switch (
|
349
|
+
switch ( _puma_parser_actions[_acts++] )
|
350
350
|
{
|
351
351
|
case 0:
|
352
352
|
// line 13 "ext/puma_http11/http11_parser.java.rl"
|
@@ -479,10 +479,10 @@ case 5:
|
|
479
479
|
}
|
480
480
|
|
481
481
|
public boolean has_error() {
|
482
|
-
return parser.cs ==
|
482
|
+
return parser.cs == puma_parser_error;
|
483
483
|
}
|
484
484
|
|
485
485
|
public boolean is_finished() {
|
486
|
-
return parser.cs ==
|
486
|
+
return parser.cs == puma_parser_first_final;
|
487
487
|
}
|
488
488
|
}
|
data/lib/puma.rb
CHANGED
data/lib/puma/app/status.rb
CHANGED
@@ -49,7 +49,7 @@ module Puma
|
|
49
49
|
end
|
50
50
|
|
51
51
|
when /\/reload-worker-directory$/
|
52
|
-
if !@cli.reload_worker_directory
|
52
|
+
if !@cli.send(:reload_worker_directory)
|
53
53
|
return rack_response(404, '{ "error": "reload_worker_directory not available" }')
|
54
54
|
else
|
55
55
|
return rack_response(200, OK_STATUS)
|
data/lib/puma/binder.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'puma/const'
|
2
|
+
require 'uri'
|
2
3
|
|
3
4
|
module Puma
|
4
5
|
class Binder
|
@@ -165,7 +166,7 @@ module Puma
|
|
165
166
|
@events.error "Please specify the SSL ca via 'ca='"
|
166
167
|
end
|
167
168
|
end
|
168
|
-
|
169
|
+
|
169
170
|
ctx.ca = params['ca'] if params['ca']
|
170
171
|
|
171
172
|
if params['verify_mode']
|
@@ -237,10 +238,14 @@ module Puma
|
|
237
238
|
end
|
238
239
|
s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
239
240
|
s.listen backlog
|
241
|
+
@connected_port = s.addr[1]
|
242
|
+
|
240
243
|
@ios << s
|
241
244
|
s
|
242
245
|
end
|
243
246
|
|
247
|
+
attr_reader :connected_port
|
248
|
+
|
244
249
|
def inherit_tcp_listener(host, port, fd)
|
245
250
|
if fd.kind_of? TCPServer
|
246
251
|
s = fd
|
data/lib/puma/cli.rb
CHANGED
@@ -1,17 +1,7 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'uri'
|
3
3
|
|
4
|
-
require 'puma/
|
5
|
-
require 'puma/const'
|
6
|
-
require 'puma/configuration'
|
7
|
-
require 'puma/binder'
|
8
|
-
require 'puma/detect'
|
9
|
-
require 'puma/daemon_ext'
|
10
|
-
require 'puma/util'
|
11
|
-
require 'puma/single'
|
12
|
-
require 'puma/cluster'
|
13
|
-
|
14
|
-
require 'puma/commonlogger'
|
4
|
+
require 'puma/launcher'
|
15
5
|
|
16
6
|
module Puma
|
17
7
|
class << self
|
@@ -25,11 +15,7 @@ module Puma
|
|
25
15
|
# Handles invoke a Puma::Server in a command line style.
|
26
16
|
#
|
27
17
|
class CLI
|
28
|
-
KEYS_NOT_TO_PERSIST_IN_STATE =
|
29
|
-
:logger, :lowlevel_error_handler,
|
30
|
-
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
31
|
-
:after_worker_boot, :before_fork, :on_restart
|
32
|
-
]
|
18
|
+
KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
|
33
19
|
|
34
20
|
# Create a new CLI object using +argv+ as the command line
|
35
21
|
# arguments.
|
@@ -39,544 +25,189 @@ module Puma
|
|
39
25
|
#
|
40
26
|
def initialize(argv, events=Events.stdio)
|
41
27
|
@debug = false
|
42
|
-
@argv = argv
|
28
|
+
@argv = argv.dup
|
43
29
|
|
44
30
|
@events = events
|
45
31
|
|
46
|
-
@
|
47
|
-
@runner = nil
|
32
|
+
@conf = nil
|
48
33
|
|
49
|
-
@
|
34
|
+
@stdout = nil
|
35
|
+
@stderr = nil
|
36
|
+
@append = false
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@binder = Binder.new(@events)
|
55
|
-
@binder.import_from_env
|
56
|
-
end
|
57
|
-
|
58
|
-
# The Binder object containing the sockets bound to.
|
59
|
-
attr_reader :binder
|
60
|
-
|
61
|
-
# The Configuration object used.
|
62
|
-
attr_reader :config
|
63
|
-
|
64
|
-
# The Hash of options used to configure puma.
|
65
|
-
attr_reader :options
|
66
|
-
|
67
|
-
# The Events object used to output information.
|
68
|
-
attr_reader :events
|
69
|
-
|
70
|
-
# Delegate +log+ to +@events+
|
71
|
-
#
|
72
|
-
def log(str)
|
73
|
-
@events.log str
|
74
|
-
end
|
75
|
-
|
76
|
-
# Delegate +error+ to +@events+
|
77
|
-
#
|
78
|
-
def error(str)
|
79
|
-
@events.error str
|
80
|
-
end
|
81
|
-
|
82
|
-
def debug(str)
|
83
|
-
@events.log "- #{str}" if @options[:debug]
|
84
|
-
end
|
85
|
-
|
86
|
-
def clustered?
|
87
|
-
@options[:workers] > 0
|
88
|
-
end
|
89
|
-
|
90
|
-
def prune_bundler?
|
91
|
-
@options[:prune_bundler] && clustered? && !@options[:preload_app]
|
92
|
-
end
|
93
|
-
|
94
|
-
def jruby?
|
95
|
-
IS_JRUBY
|
96
|
-
end
|
97
|
-
|
98
|
-
def windows?
|
99
|
-
RUBY_PLATFORM =~ /mswin32|ming32/
|
100
|
-
end
|
101
|
-
|
102
|
-
def env
|
103
|
-
@options[:environment] || @cli_options[:environment] || ENV['RACK_ENV'] || 'development'
|
104
|
-
end
|
38
|
+
@control_url = nil
|
39
|
+
@control_options = {}
|
105
40
|
|
106
|
-
|
107
|
-
write_pid
|
108
|
-
|
109
|
-
path = @options[:state]
|
110
|
-
return unless path
|
111
|
-
|
112
|
-
state = { 'pid' => Process.pid }
|
113
|
-
cfg = @config.dup
|
114
|
-
|
115
|
-
KEYS_NOT_TO_PERSIST_IN_STATE.each { |k| cfg.options.delete(k) }
|
116
|
-
state['config'] = cfg
|
117
|
-
|
118
|
-
require 'yaml'
|
119
|
-
File.open(path, 'w') { |f| f.write state.to_yaml }
|
120
|
-
end
|
121
|
-
|
122
|
-
# If configured, write the pid of the current process out
|
123
|
-
# to a file.
|
124
|
-
#
|
125
|
-
def write_pid
|
126
|
-
path = @options[:pidfile]
|
127
|
-
return unless path
|
128
|
-
|
129
|
-
File.open(path, 'w') { |f| f.puts Process.pid }
|
130
|
-
cur = Process.pid
|
131
|
-
at_exit do
|
132
|
-
delete_pidfile if cur == Process.pid
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def delete_pidfile
|
137
|
-
path = @options[:pidfile]
|
138
|
-
File.unlink(path) if path && File.exist?(path)
|
139
|
-
end
|
140
|
-
|
141
|
-
def graceful_stop
|
142
|
-
@runner.stop_blocked
|
143
|
-
log "=== puma shutdown: #{Time.now} ==="
|
144
|
-
log "- Goodbye!"
|
145
|
-
end
|
146
|
-
|
147
|
-
def jruby_daemon_start
|
148
|
-
require 'puma/jruby_restart'
|
149
|
-
JRubyRestart.daemon_start(@restart_dir, restart_args)
|
150
|
-
end
|
41
|
+
setup_options
|
151
42
|
|
152
|
-
|
153
|
-
|
154
|
-
block.call self
|
155
|
-
end
|
43
|
+
begin
|
44
|
+
@parser.parse! @argv
|
156
45
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
JRubyRestart.chdir_exec(@restart_dir, restart_args)
|
162
|
-
elsif windows?
|
163
|
-
close_binder_listeners
|
164
|
-
|
165
|
-
argv = restart_args
|
166
|
-
Dir.chdir(@restart_dir)
|
167
|
-
argv += [redirects] if RUBY_VERSION >= '1.9'
|
168
|
-
Kernel.exec(*argv)
|
169
|
-
else
|
170
|
-
redirects = {:close_others => true}
|
171
|
-
@binder.listeners.each_with_index do |(l, io), i|
|
172
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
173
|
-
redirects[io.to_i] = io.to_i
|
46
|
+
if file = @argv.shift
|
47
|
+
@conf.configure do |c|
|
48
|
+
c.rackup file
|
49
|
+
end
|
174
50
|
end
|
175
|
-
|
176
|
-
argv = restart_args
|
177
|
-
Dir.chdir(@restart_dir)
|
178
|
-
argv += [redirects] if RUBY_VERSION >= '1.9'
|
179
|
-
Kernel.exec(*argv)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
# Parse the options, load the rackup, start the server and wait
|
184
|
-
# for it to finish.
|
185
|
-
#
|
186
|
-
def run
|
187
|
-
begin
|
188
|
-
parse_options
|
189
51
|
rescue UnsupportedOption
|
190
52
|
exit 1
|
191
53
|
end
|
192
54
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
set_rack_environment
|
199
|
-
|
200
|
-
if clustered?
|
201
|
-
@events.formatter = Events::PidFormatter.new
|
202
|
-
@options[:logger] = @events
|
203
|
-
|
204
|
-
@runner = Cluster.new(self)
|
205
|
-
else
|
206
|
-
@runner = Single.new(self)
|
207
|
-
end
|
208
|
-
|
209
|
-
setup_signals
|
210
|
-
set_process_title
|
211
|
-
|
212
|
-
@status = :run
|
213
|
-
|
214
|
-
@runner.run
|
215
|
-
|
216
|
-
case @status
|
217
|
-
when :halt
|
218
|
-
log "* Stopping immediately!"
|
219
|
-
when :run, :stop
|
220
|
-
graceful_stop
|
221
|
-
when :restart
|
222
|
-
log "* Restarting..."
|
223
|
-
@runner.before_restart
|
224
|
-
restart!
|
225
|
-
when :exit
|
226
|
-
# nothing
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def stop
|
231
|
-
@status = :stop
|
232
|
-
@runner.stop
|
233
|
-
end
|
234
|
-
|
235
|
-
def restart
|
236
|
-
@status = :restart
|
237
|
-
@runner.restart
|
238
|
-
end
|
239
|
-
|
240
|
-
def reload_worker_directory
|
241
|
-
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
242
|
-
end
|
55
|
+
@conf.configure do |c|
|
56
|
+
if @stdout || @stderr
|
57
|
+
c.stdout_redirect @stdout, @stderr, @append
|
58
|
+
end
|
243
59
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
return restart
|
60
|
+
if @control_url
|
61
|
+
c.activate_control_app @control_url, @control_options
|
62
|
+
end
|
248
63
|
end
|
249
|
-
true
|
250
|
-
end
|
251
64
|
|
252
|
-
|
253
|
-
@runner.redirect_io
|
65
|
+
@launcher = Puma::Launcher.new(@conf, :events => @events, :argv => argv)
|
254
66
|
end
|
255
67
|
|
256
|
-
|
257
|
-
@runner.stats
|
258
|
-
end
|
68
|
+
attr_reader :launcher
|
259
69
|
|
260
|
-
|
261
|
-
|
262
|
-
|
70
|
+
# Parse the options, load the rackup, start the server and wait
|
71
|
+
# for it to finish.
|
72
|
+
#
|
73
|
+
def run
|
74
|
+
@launcher.run
|
263
75
|
end
|
264
76
|
|
265
77
|
private
|
266
|
-
def title
|
267
|
-
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
268
|
-
buffer << " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
269
|
-
buffer
|
270
|
-
end
|
271
|
-
|
272
78
|
def unsupported(str)
|
273
79
|
@events.error(str)
|
274
80
|
raise UnsupportedOption
|
275
81
|
end
|
276
82
|
|
277
|
-
def restart_args
|
278
|
-
cmd = @options[:restart_cmd]
|
279
|
-
if cmd
|
280
|
-
cmd.split(' ') + @original_argv
|
281
|
-
else
|
282
|
-
@restart_argv
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def set_process_title
|
287
|
-
Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
|
288
|
-
end
|
289
|
-
|
290
|
-
def find_config
|
291
|
-
if @cli_options[:config_file] == '-'
|
292
|
-
@cli_options[:config_file] = nil
|
293
|
-
else
|
294
|
-
@cli_options[:config_file] ||= %W(config/puma/#{env}.rb config/puma.rb).find { |f| File.exist?(f) }
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
83
|
# Build the OptionParser object to handle the available options.
|
299
84
|
#
|
300
85
|
|
301
86
|
def setup_options
|
302
|
-
@
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
307
|
-
(@cli_options[:binds] ||= []) << arg
|
308
|
-
end
|
309
|
-
|
310
|
-
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
311
|
-
@cli_options[:config_file] = arg
|
312
|
-
end
|
313
|
-
|
314
|
-
o.on "--control URL", "The bind url to use for the control server",
|
315
|
-
"Use 'auto' to use temp unix server" do |arg|
|
316
|
-
if arg
|
317
|
-
@cli_options[:control_url] = arg
|
318
|
-
elsif jruby?
|
319
|
-
unsupported "No default url available on JRuby"
|
87
|
+
@conf = Configuration.new do |c|
|
88
|
+
@parser = OptionParser.new do |o|
|
89
|
+
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
90
|
+
c.bind arg
|
320
91
|
end
|
321
|
-
end
|
322
92
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
end
|
327
|
-
|
328
|
-
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
329
|
-
@cli_options[:daemon] = true
|
330
|
-
@cli_options[:quiet] = true
|
331
|
-
end
|
332
|
-
|
333
|
-
o.on "--debug", "Log lowlevel debugging information" do
|
334
|
-
@cli_options[:debug] = true
|
335
|
-
end
|
336
|
-
|
337
|
-
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
338
|
-
@cli_options[:directory] = d.to_s
|
339
|
-
@cli_options[:worker_directory] = d.to_s
|
340
|
-
end
|
341
|
-
|
342
|
-
o.on "-e", "--environment ENVIRONMENT",
|
343
|
-
"The environment to run the Rack app on (default development)" do |arg|
|
344
|
-
@cli_options[:environment] = arg
|
345
|
-
end
|
346
|
-
|
347
|
-
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
348
|
-
$LOAD_PATH.unshift(*arg.split(':'))
|
349
|
-
end
|
350
|
-
|
351
|
-
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
352
|
-
"Use -b for more advanced options" do |arg|
|
353
|
-
binds = (@cli_options[:binds] ||= [])
|
354
|
-
binds << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
|
355
|
-
end
|
356
|
-
|
357
|
-
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
|
358
|
-
@cli_options[:pidfile] = arg
|
359
|
-
end
|
360
|
-
|
361
|
-
o.on "--preload", "Preload the app. Cluster mode only" do
|
362
|
-
@cli_options[:preload_app] = true
|
363
|
-
end
|
364
|
-
|
365
|
-
o.on "--prune-bundler", "Prune out the bundler env if possible" do
|
366
|
-
@cli_options[:prune_bundler] = true
|
367
|
-
end
|
368
|
-
|
369
|
-
o.on "-q", "--quiet", "Quiet down the output" do
|
370
|
-
@cli_options[:quiet] = true
|
371
|
-
end
|
372
|
-
|
373
|
-
o.on "-R", "--restart-cmd CMD",
|
374
|
-
"The puma command to run during a hot restart",
|
375
|
-
"Default: inferred" do |cmd|
|
376
|
-
@cli_options[:restart_cmd] = cmd
|
377
|
-
end
|
93
|
+
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
94
|
+
c.load arg
|
95
|
+
end
|
378
96
|
|
379
|
-
|
380
|
-
|
381
|
-
|
97
|
+
o.on "--control URL", "The bind url to use for the control server",
|
98
|
+
"Use 'auto' to use temp unix server" do |arg|
|
99
|
+
if arg
|
100
|
+
@control_url = arg
|
101
|
+
elsif Puma.jruby?
|
102
|
+
unsupported "No default url available on JRuby"
|
103
|
+
end
|
104
|
+
end
|
382
105
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
@cli_options[:min_threads] = min
|
387
|
-
@cli_options[:max_threads] = max
|
388
|
-
else
|
389
|
-
@cli_options[:min_threads] = 0
|
390
|
-
@cli_options[:max_threads] = arg
|
106
|
+
o.on "--control-token TOKEN",
|
107
|
+
"The token to use as authentication for the control server" do |arg|
|
108
|
+
@control_options[:auth_token] = arg
|
391
109
|
end
|
392
|
-
end
|
393
110
|
|
394
|
-
|
395
|
-
|
396
|
-
|
111
|
+
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
112
|
+
c.daemonize
|
113
|
+
c.quiet
|
114
|
+
end
|
397
115
|
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
end
|
116
|
+
o.on "--debug", "Log lowlevel debugging information" do
|
117
|
+
c.debug
|
118
|
+
end
|
402
119
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
end
|
120
|
+
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
121
|
+
c.directory d
|
122
|
+
end
|
407
123
|
|
408
|
-
|
409
|
-
|
410
|
-
|
124
|
+
o.on "-e", "--environment ENVIRONMENT",
|
125
|
+
"The environment to run the Rack app on (default development)" do |arg|
|
126
|
+
c.environment arg
|
127
|
+
end
|
411
128
|
|
412
|
-
|
413
|
-
|
414
|
-
|
129
|
+
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
130
|
+
$LOAD_PATH.unshift(*arg.split(':'))
|
131
|
+
end
|
415
132
|
|
416
|
-
|
417
|
-
|
418
|
-
|
133
|
+
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
134
|
+
"Use -b for more advanced options" do |arg|
|
135
|
+
c.bind "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
|
136
|
+
end
|
419
137
|
|
420
|
-
|
421
|
-
|
422
|
-
|
138
|
+
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
|
139
|
+
c.pidfile arg
|
140
|
+
end
|
423
141
|
|
424
|
-
|
142
|
+
o.on "--preload", "Preload the app. Cluster mode only" do
|
143
|
+
c.preload_app!
|
144
|
+
end
|
425
145
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
146
|
+
o.on "--prune-bundler", "Prune out the bundler env if possible" do
|
147
|
+
c.prune_bundler
|
148
|
+
end
|
432
149
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
# the pwd is /data/releases/current.
|
437
|
-
if dir = ENV['PWD']
|
438
|
-
s_env = File.stat(dir)
|
439
|
-
s_pwd = File.stat(Dir.pwd)
|
440
|
-
|
441
|
-
if s_env.ino == s_pwd.ino and (jruby? or s_env.dev == s_pwd.dev)
|
442
|
-
@restart_dir = dir
|
443
|
-
@options[:worker_directory] = dir
|
444
|
-
end
|
445
|
-
end
|
150
|
+
o.on "-q", "--quiet", "Quiet down the output" do
|
151
|
+
c.quiet
|
152
|
+
end
|
446
153
|
|
447
|
-
|
154
|
+
o.on "-R", "--restart-cmd CMD",
|
155
|
+
"The puma command to run during a hot restart",
|
156
|
+
"Default: inferred" do |cmd|
|
157
|
+
c.restart_command cmd
|
158
|
+
end
|
448
159
|
|
449
|
-
|
160
|
+
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
161
|
+
c.state_path arg
|
162
|
+
end
|
450
163
|
|
451
|
-
|
164
|
+
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
|
165
|
+
min, max = arg.split(":")
|
166
|
+
if max
|
167
|
+
c.threads min, max
|
168
|
+
else
|
169
|
+
c.threads 0, max
|
170
|
+
end
|
171
|
+
end
|
452
172
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
#
|
457
|
-
if File.exist?($0)
|
458
|
-
arg0 = [Gem.ruby, $0]
|
459
|
-
else
|
460
|
-
arg0 = [Gem.ruby, "-S", $0]
|
461
|
-
end
|
173
|
+
o.on "--tcp-mode", "Run the app in raw TCP mode instead of HTTP mode" do
|
174
|
+
c.tcp_mode!
|
175
|
+
end
|
462
176
|
|
463
|
-
|
464
|
-
|
465
|
-
|
177
|
+
o.on "-V", "--version", "Print the version information" do
|
178
|
+
puts "puma version #{Puma::Const::VERSION}"
|
179
|
+
exit 0
|
180
|
+
end
|
466
181
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
end
|
472
|
-
end
|
182
|
+
o.on "-w", "--workers COUNT",
|
183
|
+
"Activate cluster mode: How many worker processes to create" do |arg|
|
184
|
+
c.workers arg
|
185
|
+
end
|
473
186
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
end
|
187
|
+
o.on "--tag NAME", "Additional text to display in process listing" do |arg|
|
188
|
+
c.tag arg
|
189
|
+
end
|
478
190
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
restart
|
483
|
-
end
|
484
|
-
rescue Exception
|
485
|
-
log "*** SIGUSR2 not implemented, signal based restart unavailable!"
|
486
|
-
end
|
191
|
+
o.on "--redirect-stdout FILE", "Redirect STDOUT to a specific file" do |arg|
|
192
|
+
@stdout = arg.to_s
|
193
|
+
end
|
487
194
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
end
|
492
|
-
rescue Exception
|
493
|
-
log "*** SIGUSR1 not implemented, signal based restart unavailable!"
|
494
|
-
end
|
195
|
+
o.on "--redirect-stderr FILE", "Redirect STDERR to a specific file" do |arg|
|
196
|
+
@stderr = arg.to_s
|
197
|
+
end
|
495
198
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
end
|
500
|
-
rescue Exception
|
501
|
-
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
502
|
-
end
|
199
|
+
o.on "--[no-]redirect-append", "Append to redirected files" do |val|
|
200
|
+
@append = val
|
201
|
+
end
|
503
202
|
|
504
|
-
|
505
|
-
Signal.trap "SIGHUP" do
|
506
|
-
redirect_io
|
507
|
-
end
|
508
|
-
rescue Exception
|
509
|
-
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
510
|
-
end
|
203
|
+
o.banner = "puma <options> <rackup file>"
|
511
204
|
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
exit
|
205
|
+
o.on_tail "-h", "--help", "Show help" do
|
206
|
+
$stdout.puts o
|
207
|
+
exit 0
|
208
|
+
end
|
517
209
|
end
|
518
210
|
end
|
519
211
|
end
|
520
|
-
|
521
|
-
def close_binder_listeners
|
522
|
-
@binder.listeners.each do |l, io|
|
523
|
-
io.close
|
524
|
-
uri = URI.parse(l)
|
525
|
-
next unless uri.scheme == 'unix'
|
526
|
-
File.unlink("#{uri.host}#{uri.path}")
|
527
|
-
end
|
528
|
-
end
|
529
|
-
|
530
|
-
def parse_options
|
531
|
-
@parser.parse! @argv
|
532
|
-
|
533
|
-
@cli_options[:rackup] = @argv.shift if @argv.last
|
534
|
-
|
535
|
-
find_config
|
536
|
-
|
537
|
-
@config = Puma::Configuration.new @cli_options
|
538
|
-
|
539
|
-
# Advertise the Configuration
|
540
|
-
Puma.cli_config = @config
|
541
|
-
|
542
|
-
@config.load
|
543
|
-
|
544
|
-
@options = @config.options
|
545
|
-
|
546
|
-
if clustered? && (jruby? || windows?)
|
547
|
-
unsupported 'worker mode not supported on JRuby or Windows'
|
548
|
-
end
|
549
|
-
|
550
|
-
if @options[:daemon] && windows?
|
551
|
-
unsupported 'daemon mode not supported on Windows'
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
def prune_bundler
|
556
|
-
return unless defined?(Bundler)
|
557
|
-
puma = Bundler.rubygems.loaded_specs("puma")
|
558
|
-
dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
|
559
|
-
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
|
560
|
-
|
561
|
-
unless puma_lib_dir
|
562
|
-
log "! Unable to prune Bundler environment, continuing"
|
563
|
-
return
|
564
|
-
end
|
565
|
-
|
566
|
-
deps = puma.runtime_dependencies.map do |d|
|
567
|
-
spec = Bundler.rubygems.loaded_specs(d.name)
|
568
|
-
"#{d.name}:#{spec.version.to_s}"
|
569
|
-
end
|
570
|
-
|
571
|
-
log '* Pruning Bundler environment'
|
572
|
-
home = ENV['GEM_HOME']
|
573
|
-
Bundler.with_clean_env do
|
574
|
-
ENV['GEM_HOME'] = home
|
575
|
-
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
576
|
-
wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
577
|
-
args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
578
|
-
Kernel.exec(*args)
|
579
|
-
end
|
580
|
-
end
|
581
212
|
end
|
582
213
|
end
|