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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 761911bec0cc543faf03994736a763dc7d87b6eb
4
- data.tar.gz: 20cd1109cf893a9940549520e1f2e6c875532f2e
3
+ metadata.gz: ec0eeb5886074470b19df49db748d9fad55c57c6
4
+ data.tar.gz: 74521d8b05a10a149cf6aa0fb4dc4c7e199ab124
5
5
  SHA512:
6
- metadata.gz: c655e44ef966f2a4d8acd9b3d96b11a13072993edb1049ca65470cc0af3460bcd2e0d3f57f8afcec203cf6d9caad85cc7f1849454374ed65949b4284bd27ea33
7
- data.tar.gz: 9b0e3acb94d4b0e3ae1a0f1eb1279dba87d600df67c928b455d8ea3ad47f3f90fb0a6854920776bad809dd46d013441e95385b981472d5f81f88d19ecbf4560e
6
+ metadata.gz: d64e58108913abf1b2252ba3038553ec28c82cfe96aa8812de7bdc58215881aea90a1048b490cee8699df99c73f3ea2b9d1dd3b472d082fbcc7974003c79e16c
7
+ data.tar.gz: 35befe3e0a9d01fa14f58841ecbcef2fa84a99ba8b3c564ceacb99101e52d50a855c7ab65c983caf816a09bf5547fb35b4e6f111985bea1cb5940e46a01b4dc8
@@ -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) [![Build Status](https://secure.travis-ci.org/puma/puma.png)](http://travis-ci.org/puma/puma) [![Dependency Status](https://gemnasium.com/puma/puma.png)](https://gemnasium.com/puma/puma) <a href="https://codeclimate.com/github/puma/puma"><img src="https://codeclimate.com/github/puma/puma.png" /></a>
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 http_parser;
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 http_parser_common "http11_parser_common.rl";
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 == http_parser_error;
155
+ return parser.cs == puma_parser_error;
156
156
  }
157
157
 
158
158
  public boolean is_finished() {
159
- return parser.cs == http_parser_first_final;
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[] init__http_parser_actions_0()
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 _http_parser_actions[] = init__http_parser_actions_0();
28
+ private static final byte _puma_parser_actions[] = init__puma_parser_actions_0();
29
29
 
30
30
 
31
- private static short[] init__http_parser_key_offsets_0()
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 _http_parser_key_offsets[] = init__http_parser_key_offsets_0();
42
+ private static final short _puma_parser_key_offsets[] = init__puma_parser_key_offsets_0();
43
43
 
44
44
 
45
- private static char[] init__http_parser_trans_keys_0()
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 _http_parser_trans_keys[] = init__http_parser_trans_keys_0();
83
+ private static final char _puma_parser_trans_keys[] = init__puma_parser_trans_keys_0();
84
84
 
85
85
 
86
- private static byte[] init__http_parser_single_lengths_0()
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 _http_parser_single_lengths[] = init__http_parser_single_lengths_0();
97
+ private static final byte _puma_parser_single_lengths[] = init__puma_parser_single_lengths_0();
98
98
 
99
99
 
100
- private static byte[] init__http_parser_range_lengths_0()
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 _http_parser_range_lengths[] = init__http_parser_range_lengths_0();
111
+ private static final byte _puma_parser_range_lengths[] = init__puma_parser_range_lengths_0();
112
112
 
113
113
 
114
- private static short[] init__http_parser_index_offsets_0()
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 _http_parser_index_offsets[] = init__http_parser_index_offsets_0();
125
+ private static final short _puma_parser_index_offsets[] = init__puma_parser_index_offsets_0();
126
126
 
127
127
 
128
- private static byte[] init__http_parser_indicies_0()
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 _http_parser_indicies[] = init__http_parser_indicies_0();
161
+ private static final byte _puma_parser_indicies[] = init__puma_parser_indicies_0();
162
162
 
163
163
 
164
- private static byte[] init__http_parser_trans_targs_0()
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 _http_parser_trans_targs[] = init__http_parser_trans_targs_0();
177
+ private static final byte _puma_parser_trans_targs[] = init__puma_parser_trans_targs_0();
178
178
 
179
179
 
180
- private static byte[] init__http_parser_trans_actions_0()
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 _http_parser_trans_actions[] = init__http_parser_trans_actions_0();
193
+ private static final byte _puma_parser_trans_actions[] = init__puma_parser_trans_actions_0();
194
194
 
195
195
 
196
- static final int http_parser_start = 1;
197
- static final int http_parser_first_final = 57;
198
- static final int http_parser_error = 0;
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 http_parser_en_main = 1;
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 = http_parser_start;
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 = _http_parser_key_offsets[cs];
294
- _trans = _http_parser_index_offsets[cs];
295
- _klen = _http_parser_single_lengths[cs];
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] < _http_parser_trans_keys[_mid] )
305
+ if ( data[p] < _puma_parser_trans_keys[_mid] )
306
306
  _upper = _mid - 1;
307
- else if ( data[p] > _http_parser_trans_keys[_mid] )
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 = _http_parser_range_lengths[cs];
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] < _http_parser_trans_keys[_mid] )
328
+ if ( data[p] < _puma_parser_trans_keys[_mid] )
329
329
  _upper = _mid - 2;
330
- else if ( data[p] > _http_parser_trans_keys[_mid+1] )
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 = _http_parser_indicies[_trans];
342
- cs = _http_parser_trans_targs[_trans];
341
+ _trans = _puma_parser_indicies[_trans];
342
+ cs = _puma_parser_trans_targs[_trans];
343
343
 
344
- if ( _http_parser_trans_actions[_trans] != 0 ) {
345
- _acts = _http_parser_trans_actions[_trans];
346
- _nacts = (int) _http_parser_actions[_acts++];
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 ( _http_parser_actions[_acts++] )
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 == http_parser_error;
482
+ return parser.cs == puma_parser_error;
483
483
  }
484
484
 
485
485
  public boolean is_finished() {
486
- return parser.cs == http_parser_first_final;
486
+ return parser.cs == puma_parser_first_final;
487
487
  }
488
488
  }
@@ -12,3 +12,4 @@ require 'thread'
12
12
  # Ruby Puma
13
13
  require 'puma/const'
14
14
  require 'puma/server'
15
+ require 'puma/launcher'
@@ -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)
@@ -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
@@ -1,17 +1,7 @@
1
1
  require 'optparse'
2
2
  require 'uri'
3
3
 
4
- require 'puma/server'
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
- @status = nil
47
- @runner = nil
32
+ @conf = nil
48
33
 
49
- @config = nil
34
+ @stdout = nil
35
+ @stderr = nil
36
+ @append = false
50
37
 
51
- setup_options
52
- generate_restart_data
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
- def write_state
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
- def restart!
153
- @options[:on_restart].each do |block|
154
- block.call self
155
- end
43
+ begin
44
+ @parser.parse! @argv
156
45
 
157
- if jruby?
158
- close_binder_listeners
159
-
160
- require 'puma/jruby_restart'
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
- dir = @options[:directory]
194
- Dir.chdir(dir) if dir
195
-
196
- prune_bundler if prune_bundler?
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
- def phased_restart
245
- unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
246
- log "* phased-restart called but not available, restarting normally."
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
- def redirect_io
253
- @runner.redirect_io
65
+ @launcher = Puma::Launcher.new(@conf, :events => @events, :argv => argv)
254
66
  end
255
67
 
256
- def stats
257
- @runner.stats
258
- end
68
+ attr_reader :launcher
259
69
 
260
- def halt
261
- @status = :halt
262
- @runner.halt
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
- @cli_options = {}
303
- @options = {}
304
-
305
- @parser = OptionParser.new do |o|
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
- o.on "--control-token TOKEN",
324
- "The token to use as authentication for the control server" do |arg|
325
- @cli_options[:control_auth_token] = arg
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
- o.on "-S", "--state PATH", "Where to store the state details" do |arg|
380
- @cli_options[:state] = arg
381
- end
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
- o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
384
- min, max = arg.split(":")
385
- if max
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
- o.on "--tcp-mode", "Run the app in raw TCP mode instead of HTTP mode" do
395
- @cli_options[:mode] = :tcp
396
- end
111
+ o.on "-d", "--daemon", "Daemonize the server into the background" do
112
+ c.daemonize
113
+ c.quiet
114
+ end
397
115
 
398
- o.on "-V", "--version", "Print the version information" do
399
- puts "puma version #{Puma::Const::VERSION}"
400
- exit 0
401
- end
116
+ o.on "--debug", "Log lowlevel debugging information" do
117
+ c.debug
118
+ end
402
119
 
403
- o.on "-w", "--workers COUNT",
404
- "Activate cluster mode: How many worker processes to create" do |arg|
405
- @cli_options[:workers] = arg.to_i
406
- end
120
+ o.on "--dir DIR", "Change to DIR before starting" do |d|
121
+ c.directory d
122
+ end
407
123
 
408
- o.on "--tag NAME", "Additional text to display in process listing" do |arg|
409
- @cli_options[:tag] = arg
410
- end
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
- o.on "--redirect-stdout FILE", "Redirect STDOUT to a specific file" do |arg|
413
- @cli_options[:redirect_stdout] = arg
414
- end
129
+ o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
130
+ $LOAD_PATH.unshift(*arg.split(':'))
131
+ end
415
132
 
416
- o.on "--redirect-stderr FILE", "Redirect STDERR to a specific file" do |arg|
417
- @cli_options[:redirect_stderr] = arg
418
- end
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
- o.on "--[no-]redirect-append", "Append to redirected files" do |val|
421
- @cli_options[:redirect_append] = val
422
- end
138
+ o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
139
+ c.pidfile arg
140
+ end
423
141
 
424
- o.banner = "puma <options> <rackup file>"
142
+ o.on "--preload", "Preload the app. Cluster mode only" do
143
+ c.preload_app!
144
+ end
425
145
 
426
- o.on_tail "-h", "--help", "Show help" do
427
- log o
428
- exit 0
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
- def generate_restart_data
434
- # Use the same trick as unicorn, namely favor PWD because
435
- # it will contain an unresolved symlink, useful for when
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
- @restart_dir ||= Dir.pwd
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
- @original_argv = @argv.dup
160
+ o.on "-S", "--state PATH", "Where to store the state details" do |arg|
161
+ c.state_path arg
162
+ end
450
163
 
451
- require 'rubygems'
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
- # if $0 is a file in the current directory, then restart
454
- # it the same, otherwise add -S on there because it was
455
- # picked up in PATH.
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
- # Detect and reinject -Ilib from the command line
464
- lib = File.expand_path "lib"
465
- arg0[1,0] = ["-I", lib] if $:[0] == lib
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
- if defined? Puma::WILD_ARGS
468
- @restart_argv = arg0 + Puma::WILD_ARGS + @original_argv
469
- else
470
- @restart_argv = arg0 + @original_argv
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
- def set_rack_environment
475
- @options[:environment] = env
476
- ENV['RACK_ENV'] = env
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
- def setup_signals
480
- begin
481
- Signal.trap "SIGUSR2" do
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
- begin
489
- Signal.trap "SIGUSR1" do
490
- phased_restart
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
- begin
497
- Signal.trap "SIGTERM" do
498
- stop
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
- begin
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
- if jruby?
513
- Signal.trap("INT") do
514
- @status = :exit
515
- graceful_stop
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