puma 2.11.1-java → 2.11.2-java

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.

data/lib/puma/const.rb CHANGED
@@ -28,7 +28,7 @@ module Puma
28
28
  # too taxing on performance.
29
29
  module Const
30
30
 
31
- PUMA_VERSION = VERSION = "2.11.1".freeze
31
+ PUMA_VERSION = VERSION = "2.11.2".freeze
32
32
  CODE_NAME = "Intrepid Squirrel".freeze
33
33
 
34
34
  FAST_TRACK_KA_TIMEOUT = 0.2
data/lib/puma/dsl.rb ADDED
@@ -0,0 +1,280 @@
1
+ module Puma
2
+ # The methods that are available for use inside the config file.
3
+ #
4
+ class DSL
5
+ include ConfigDefault
6
+
7
+ def self.load(options, path)
8
+ new(options).tap do |obj|
9
+ obj._load_from(path)
10
+ end
11
+
12
+ options
13
+ end
14
+
15
+ def initialize(options)
16
+ @options = options
17
+ end
18
+
19
+ def _load_from(path)
20
+ instance_eval(File.read(path), path, 1) if path
21
+ end
22
+
23
+ # Use +obj+ or +block+ as the Rack app. This allows a config file to
24
+ # be the app itself.
25
+ #
26
+ def app(obj=nil, &block)
27
+ obj ||= block
28
+
29
+ raise "Provide either a #call'able or a block" unless obj
30
+
31
+ @options[:app] = obj
32
+ end
33
+
34
+ # Start the Puma control rack app on +url+. This app can be communicated
35
+ # with to control the main server.
36
+ #
37
+ def activate_control_app(url="auto", opts=nil)
38
+ @options[:control_url] = url
39
+
40
+ if opts
41
+ auth_token = opts[:auth_token]
42
+ @options[:control_auth_token] = auth_token if auth_token
43
+
44
+ @options[:control_auth_token] = :none if opts[:no_token]
45
+ end
46
+ end
47
+
48
+ # Bind the server to +url+. tcp:// and unix:// are the only accepted
49
+ # protocols.
50
+ #
51
+ def bind(url)
52
+ @options[:binds] << url
53
+ end
54
+
55
+ # Define the TCP port to bind to. Use +bind+ for more advanced options.
56
+ #
57
+ def port(port)
58
+ @options[:binds] << "tcp://#{Configuration::DefaultTCPHost}:#{port}"
59
+ end
60
+
61
+ # Work around leaky apps that leave garbage in Thread locals
62
+ # across requests
63
+ #
64
+ def clean_thread_locals(which=true)
65
+ @options[:clean_thread_locals] = which
66
+ end
67
+
68
+ # Daemonize the server into the background. Highly suggest that
69
+ # this be combined with +pidfile+ and +stdout_redirect+.
70
+ def daemonize(which=true)
71
+ @options[:daemon] = which
72
+ end
73
+
74
+ # When shutting down, drain the accept socket of pending
75
+ # connections and proces them. This loops over the accept
76
+ # socket until there are no more read events and then stops
77
+ # looking and waits for the requests to finish.
78
+ def drain_on_shutdown(which=true)
79
+ @options[:drain_on_shutdown] = which
80
+ end
81
+
82
+ # Set the environment in which the Rack's app will run.
83
+ def environment(environment)
84
+ @options[:environment] = environment
85
+ end
86
+
87
+ # Code to run before doing a restart. This code should
88
+ # close logfiles, database connections, etc.
89
+ #
90
+ # This can be called multiple times to add code each time.
91
+ #
92
+ def on_restart(&block)
93
+ @options[:on_restart] << block
94
+ end
95
+
96
+ # Command to use to restart puma. This should be just how to
97
+ # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
98
+ # to puma, as those are the same as the original process.
99
+ #
100
+ def restart_command(cmd)
101
+ @options[:restart_cmd] = cmd
102
+ end
103
+
104
+ # Store the pid of the server in the file at +path+.
105
+ def pidfile(path)
106
+ @options[:pidfile] = path
107
+ end
108
+
109
+ # Disable request logging.
110
+ #
111
+ def quiet
112
+ @options[:quiet] = true
113
+ end
114
+
115
+ # Load +path+ as a rackup file.
116
+ #
117
+ def rackup(path)
118
+ @options[:rackup] = path.to_s
119
+ end
120
+
121
+ # Redirect STDOUT and STDERR to files specified.
122
+ def stdout_redirect(stdout=nil, stderr=nil, append=false)
123
+ @options[:redirect_stdout] = stdout
124
+ @options[:redirect_stderr] = stderr
125
+ @options[:redirect_append] = append
126
+ end
127
+
128
+ # Configure +min+ to be the minimum number of threads to use to answer
129
+ # requests and +max+ the maximum.
130
+ #
131
+ def threads(min, max)
132
+ min = Integer(min)
133
+ max = Integer(max)
134
+ if min > max
135
+ raise "The minimum (#{min}) number of threads must be less than the max (#{max})"
136
+ end
137
+
138
+ @options[:min_threads] = min
139
+ @options[:max_threads] = max
140
+ end
141
+
142
+ def ssl_bind(host, port, opts)
143
+ @options[:binds] << "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}"
144
+ end
145
+
146
+ # Use +path+ as the file to store the server info state. This is
147
+ # used by pumactl to query and control the server.
148
+ #
149
+ def state_path(path)
150
+ @options[:state] = path.to_s
151
+ end
152
+
153
+ # *Cluster mode only* How many worker processes to run.
154
+ #
155
+ def workers(count)
156
+ @options[:workers] = count.to_i
157
+ end
158
+
159
+ # *Cluster mode only* Code to run immediately before a worker shuts
160
+ # down (after it has finished processing HTTP requests). These hooks
161
+ # can block if necessary to wait for background operations unknown
162
+ # to puma to finish before the process terminates.
163
+ #
164
+ # This can be called multiple times to add hooks.
165
+ #
166
+ def on_worker_shutdown(&block)
167
+ @options[:before_worker_shutdown] << block
168
+ end
169
+
170
+ # *Cluster mode only* Code to run when a worker boots to setup
171
+ # the process before booting the app.
172
+ #
173
+ # This can be called multiple times to add hooks.
174
+ #
175
+ def on_worker_boot(&block)
176
+ @options[:before_worker_boot] << block
177
+ end
178
+
179
+ # *Cluster mode only* Code to run when a master process is
180
+ # about to create the worker by forking itself.
181
+ #
182
+ # This can be called multiple times to add hooks.
183
+ #
184
+ def on_worker_fork(&block)
185
+ @options[:before_worker_fork] << block
186
+ end
187
+
188
+ # *Cluster mode only* Code to run when a worker boots to setup
189
+ # the process after booting the app.
190
+ #
191
+ # This can be called multiple times to add hooks.
192
+ #
193
+ def after_worker_boot(&block)
194
+ @options[:after_worker_boot] << block
195
+ end
196
+
197
+ # The directory to operate out of.
198
+ def directory(dir)
199
+ @options[:directory] = dir.to_s
200
+ @options[:worker_directory] = dir.to_s
201
+ end
202
+
203
+ # Run the app as a raw TCP app instead of an HTTP rack app
204
+ def tcp_mode
205
+ @options[:mode] = :tcp
206
+ end
207
+
208
+ # *Cluster mode only* Preload the application before starting
209
+ # the workers and setting up the listen ports. This conflicts
210
+ # with using the phased restart feature, you can't use both.
211
+ #
212
+ def preload_app!(answer=true)
213
+ @options[:preload_app] = answer
214
+ end
215
+
216
+ # Use +obj+ or +block+ as the low level error handler. This allows a config file to
217
+ # change the default error on the server.
218
+ #
219
+ def lowlevel_error_handler(obj=nil, &block)
220
+ obj ||= block
221
+ raise "Provide either a #call'able or a block" unless obj
222
+ @options[:lowlevel_error_handler] = obj
223
+ end
224
+
225
+ # This option is used to allow your app and its gems to be
226
+ # properly reloaded when not using preload.
227
+ #
228
+ # When set, if puma detects that it's been invoked in the
229
+ # context of Bundler, it will cleanup the environment and
230
+ # re-run itself outside the Bundler environment, but directly
231
+ # using the files that Bundler has setup.
232
+ #
233
+ # This means that puma is now decoupled from your Bundler
234
+ # context and when each worker loads, it will be loading a
235
+ # new Bundler context and thus can float around as the release
236
+ # dictates.
237
+ def prune_bundler(answer=true)
238
+ @options[:prune_bundler] = answer
239
+ end
240
+
241
+ # Additional text to display in process listing
242
+ def tag(string)
243
+ @options[:tag] = string
244
+ end
245
+
246
+ # *Cluster mode only* Set the timeout for workers
247
+ def worker_timeout(timeout)
248
+ @options[:worker_timeout] = timeout
249
+ end
250
+
251
+ # *Cluster mode only* Set the timeout for worker shutdown
252
+ def worker_shutdown_timeout(timeout)
253
+ @options[:worker_shutdown_timeout] = timeout
254
+ end
255
+
256
+ # When set to true (the default), workers accept all requests
257
+ # and queue them before passing them to the handlers.
258
+ # When set to false, each worker process accepts exactly as
259
+ # many requests as it is configured to simultaneously handle.
260
+ #
261
+ # Queueing requests generally improves performance. In some
262
+ # cases, such as a single threaded application, it may be
263
+ # better to ensure requests get balanced across workers.
264
+ #
265
+ # Note that setting this to false disables HTTP keepalive and
266
+ # slow clients will occupy a handler thread while the request
267
+ # is being sent. A reverse proxy, such as nginx, can handle
268
+ # slow clients and queue requests before they reach puma.
269
+ def queue_requests(answer=true)
270
+ @options[:queue_requests] = answer
271
+ end
272
+
273
+ # When a shutdown is requested, the backtraces of all the
274
+ # threads will be written to $stdout. This can help figure
275
+ # out why shutdown is hanging.
276
+ def shutdown_debug(val=true)
277
+ @options[:shutdown_debug] = val
278
+ end
279
+ end
280
+ end
Binary file
data/lib/puma/server.rb CHANGED
@@ -535,7 +535,7 @@ module Puma
535
535
  line_ending = LINE_END
536
536
  colon = COLON
537
537
 
538
- if env[HTTP_VERSION] == HTTP_11
538
+ http_11 = if env[HTTP_VERSION] == HTTP_11
539
539
  allow_chunked = true
540
540
  keep_alive = env[HTTP_CONNECTION] != CLOSE
541
541
  include_keepalive_header = false
@@ -552,6 +552,7 @@ module Puma
552
552
 
553
553
  no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
554
554
  end
555
+ true
555
556
  else
556
557
  allow_chunked = false
557
558
  keep_alive = env[HTTP_CONNECTION] == KEEP_ALIVE
@@ -567,6 +568,7 @@ module Puma
567
568
 
568
569
  no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
569
570
  end
571
+ false
570
572
  end
571
573
 
572
574
  response_hijack = nil
@@ -593,6 +595,12 @@ module Puma
593
595
  end
594
596
  end
595
597
 
598
+ if include_keepalive_header
599
+ lines << CONNECTION_KEEP_ALIVE
600
+ elsif http_11 && !keep_alive
601
+ lines << CONNECTION_CLOSE
602
+ end
603
+
596
604
  if no_body
597
605
  if content_length and status != 204
598
606
  lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
@@ -603,12 +611,6 @@ module Puma
603
611
  return keep_alive
604
612
  end
605
613
 
606
- if include_keepalive_header
607
- lines << CONNECTION_KEEP_ALIVE
608
- elsif !keep_alive
609
- lines << CONNECTION_CLOSE
610
- end
611
-
612
614
  unless response_hijack
613
615
  if content_length
614
616
  lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
@@ -738,6 +740,21 @@ module Puma
738
740
  # Wait for all outstanding requests to finish.
739
741
  #
740
742
  def graceful_shutdown
743
+ if @options[:shutdown_debug]
744
+ threads = Thread.list
745
+ total = threads.size
746
+
747
+ pid = Process.pid
748
+
749
+ $stdout.syswrite "#{pid}: === Begin thread backtrace dump ===\n"
750
+
751
+ threads.each_with_index do |t,i|
752
+ $stdout.syswrite "#{pid}: Thread #{i+1}/#{total}: #{t.inspect}\n"
753
+ $stdout.syswrite "#{pid}: #{t.backtrace.join("\n#{pid}: ")}\n\n"
754
+ end
755
+ $stdout.syswrite "#{pid}: === End thread backtrace dump ===\n"
756
+ end
757
+
741
758
  if @options[:drain_on_shutdown]
742
759
  count = 0
743
760
 
data/puma.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
18
18
  s.authors = ["Evan Phoenix"]
19
19
  s.date = `git log --pretty="%ai" -n 1`.split(" ").first
20
- s.description = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby."
20
+ s.description = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby."
21
21
  s.email = ["evan@phx.io"]
22
22
  s.executables = ["puma", "pumactl"]
23
23
  s.extensions = ["ext/puma_http11/extconf.rb"]
data/test/test_cli.rb CHANGED
@@ -35,7 +35,7 @@ class TestCLI < Test::Unit::TestCase
35
35
 
36
36
  def test_pid_file
37
37
  cli = Puma::CLI.new ["--pidfile", @tmp_path]
38
- cli.parse_options
38
+ cli.send(:parse_options)
39
39
  cli.write_pid
40
40
 
41
41
  assert_equal File.read(@tmp_path).strip.to_i, Process.pid
@@ -48,7 +48,7 @@ class TestCLI < Test::Unit::TestCase
48
48
  "--control-token", "",
49
49
  "test/lobster.ru"], @events
50
50
 
51
- cli.parse_options
51
+ cli.send(:parse_options)
52
52
 
53
53
  thread_exception = nil
54
54
  t = Thread.new do
@@ -57,7 +57,7 @@ class TestCLI < Test::Unit::TestCase
57
57
  rescue Exception => e
58
58
  thread_exception = e
59
59
  end
60
- end
60
+ end
61
61
 
62
62
  wait_booted
63
63
 
@@ -79,7 +79,7 @@ class TestCLI < Test::Unit::TestCase
79
79
  "--control", url,
80
80
  "--control-token", "",
81
81
  "test/lobster.ru"], @events
82
- cli.parse_options
82
+ cli.send(:parse_options)
83
83
 
84
84
  t = Thread.new { cli.run }
85
85
 
@@ -102,7 +102,7 @@ class TestCLI < Test::Unit::TestCase
102
102
  "--control", url,
103
103
  "--control-token", "",
104
104
  "test/lobster.ru"], @events
105
- cli.parse_options
105
+ cli.send(:parse_options)
106
106
 
107
107
  t = Thread.new { cli.run }
108
108
 
@@ -120,7 +120,7 @@ class TestCLI < Test::Unit::TestCase
120
120
  def test_tmp_control
121
121
  url = "tcp://127.0.0.1:8232"
122
122
  cli = Puma::CLI.new ["--state", @tmp_path, "--control", "auto"]
123
- cli.parse_options
123
+ cli.send(:parse_options)
124
124
  cli.write_state
125
125
 
126
126
  data = YAML.load File.read(@tmp_path)
@@ -138,7 +138,7 @@ class TestCLI < Test::Unit::TestCase
138
138
  def test_state
139
139
  url = "tcp://127.0.0.1:8232"
140
140
  cli = Puma::CLI.new ["--state", @tmp_path, "--control", url]
141
- cli.parse_options
141
+ cli.send(:parse_options)
142
142
  cli.write_state
143
143
 
144
144
  data = YAML.load File.read(@tmp_path)
@@ -149,13 +149,13 @@ class TestCLI < Test::Unit::TestCase
149
149
 
150
150
  def test_load_path
151
151
  cli = Puma::CLI.new ["--include", 'foo/bar']
152
- cli.parse_options
152
+ cli.send(:parse_options)
153
153
 
154
154
  assert_equal 'foo/bar', $LOAD_PATH[0]
155
155
  $LOAD_PATH.shift
156
156
 
157
157
  cli = Puma::CLI.new ["--include", 'foo/bar:baz/qux']
158
- cli.parse_options
158
+ cli.send(:parse_options)
159
159
 
160
160
  assert_equal 'foo/bar', $LOAD_PATH[0]
161
161
  $LOAD_PATH.shift
@@ -165,9 +165,9 @@ class TestCLI < Test::Unit::TestCase
165
165
 
166
166
  def test_environment
167
167
  cli = Puma::CLI.new ["--environment", @environment]
168
- cli.parse_options
169
- cli.set_rack_environment
168
+ cli.send(:parse_options)
169
+ cli.send(:set_rack_environment)
170
170
 
171
- assert_equal ENV['RACK_ENV'], @environment
171
+ assert_equal ENV['RACK_ENV'], @environment
172
172
  end
173
173
  end