puma 6.0.0 → 6.4.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.

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +184 -6
  3. data/LICENSE +0 -0
  4. data/README.md +58 -13
  5. data/bin/puma-wild +0 -0
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +0 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +0 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +12 -0
  17. data/docs/nginx.md +1 -1
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +0 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +1 -2
  24. data/docs/testing_benchmarks_local_files.md +0 -0
  25. data/docs/testing_test_rackup_ci_files.md +0 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +0 -0
  29. data/ext/puma_http11/http11_parser.c +0 -0
  30. data/ext/puma_http11/http11_parser.h +0 -0
  31. data/ext/puma_http11/http11_parser.java.rl +0 -0
  32. data/ext/puma_http11/http11_parser.rl +0 -0
  33. data/ext/puma_http11/http11_parser_common.rl +0 -0
  34. data/ext/puma_http11/mini_ssl.c +91 -8
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +0 -0
  39. data/ext/puma_http11/puma_http11.c +0 -0
  40. data/lib/puma/app/status.rb +1 -1
  41. data/lib/puma/binder.rb +14 -11
  42. data/lib/puma/cli.rb +5 -1
  43. data/lib/puma/client.rb +53 -16
  44. data/lib/puma/cluster/worker.rb +5 -0
  45. data/lib/puma/cluster/worker_handle.rb +0 -0
  46. data/lib/puma/cluster.rb +5 -5
  47. data/lib/puma/commonlogger.rb +21 -14
  48. data/lib/puma/configuration.rb +5 -1
  49. data/lib/puma/const.rb +129 -88
  50. data/lib/puma/control_cli.rb +12 -5
  51. data/lib/puma/detect.rb +2 -0
  52. data/lib/puma/dsl.rb +147 -7
  53. data/lib/puma/error_logger.rb +2 -1
  54. data/lib/puma/events.rb +0 -0
  55. data/lib/puma/io_buffer.rb +10 -0
  56. data/lib/puma/jruby_restart.rb +0 -0
  57. data/lib/puma/json_serialization.rb +0 -0
  58. data/lib/puma/launcher/bundle_pruner.rb +0 -0
  59. data/lib/puma/launcher.rb +9 -22
  60. data/lib/puma/log_writer.rb +14 -4
  61. data/lib/puma/minissl/context_builder.rb +1 -0
  62. data/lib/puma/minissl.rb +17 -0
  63. data/lib/puma/plugin/systemd.rb +90 -0
  64. data/lib/puma/plugin/tmp_restart.rb +0 -0
  65. data/lib/puma/plugin.rb +0 -0
  66. data/lib/puma/rack/builder.rb +2 -2
  67. data/lib/puma/rack/urlmap.rb +1 -1
  68. data/lib/puma/rack_default.rb +18 -3
  69. data/lib/puma/reactor.rb +17 -8
  70. data/lib/puma/request.rb +189 -125
  71. data/lib/puma/runner.rb +16 -1
  72. data/lib/puma/sd_notify.rb +149 -0
  73. data/lib/puma/server.rb +74 -34
  74. data/lib/puma/single.rb +3 -1
  75. data/lib/puma/state_file.rb +0 -0
  76. data/lib/puma/thread_pool.rb +42 -7
  77. data/lib/puma/util.rb +0 -0
  78. data/lib/puma.rb +1 -3
  79. data/lib/rack/handler/puma.rb +113 -86
  80. data/tools/Dockerfile +0 -0
  81. data/tools/trickletest.rb +0 -0
  82. metadata +4 -3
  83. data/lib/puma/systemd.rb +0 -47
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+
5
+ module Puma
6
+ # The MIT License
7
+ #
8
+ # Copyright (c) 2017-2022 Agis Anastasopoulos
9
+ #
10
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
11
+ # this software and associated documentation files (the "Software"), to deal in
12
+ # the Software without restriction, including without limitation the rights to
13
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
14
+ # the Software, and to permit persons to whom the Software is furnished to do so,
15
+ # subject to the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be included in all
18
+ # copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
23
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #
27
+ # This is a copy of https://github.com/agis/ruby-sdnotify as of commit cca575c
28
+ # The only changes made was "rehoming" it within the Puma module to avoid
29
+ # namespace collisions and applying standard's code formatting style.
30
+ #
31
+ # SdNotify is a pure-Ruby implementation of sd_notify(3). It can be used to
32
+ # notify systemd about state changes. Methods of this package are no-op on
33
+ # non-systemd systems (eg. Darwin).
34
+ #
35
+ # The API maps closely to the original implementation of sd_notify(3),
36
+ # therefore be sure to check the official man pages prior to using SdNotify.
37
+ #
38
+ # @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
39
+ module SdNotify
40
+ # Exception raised when there's an error writing to the notification socket
41
+ class NotifyError < RuntimeError; end
42
+
43
+ READY = "READY=1"
44
+ RELOADING = "RELOADING=1"
45
+ STOPPING = "STOPPING=1"
46
+ STATUS = "STATUS="
47
+ ERRNO = "ERRNO="
48
+ MAINPID = "MAINPID="
49
+ WATCHDOG = "WATCHDOG=1"
50
+ FDSTORE = "FDSTORE=1"
51
+
52
+ def self.ready(unset_env=false)
53
+ notify(READY, unset_env)
54
+ end
55
+
56
+ def self.reloading(unset_env=false)
57
+ notify(RELOADING, unset_env)
58
+ end
59
+
60
+ def self.stopping(unset_env=false)
61
+ notify(STOPPING, unset_env)
62
+ end
63
+
64
+ # @param status [String] a custom status string that describes the current
65
+ # state of the service
66
+ def self.status(status, unset_env=false)
67
+ notify("#{STATUS}#{status}", unset_env)
68
+ end
69
+
70
+ # @param errno [Integer]
71
+ def self.errno(errno, unset_env=false)
72
+ notify("#{ERRNO}#{errno}", unset_env)
73
+ end
74
+
75
+ # @param pid [Integer]
76
+ def self.mainpid(pid, unset_env=false)
77
+ notify("#{MAINPID}#{pid}", unset_env)
78
+ end
79
+
80
+ def self.watchdog(unset_env=false)
81
+ notify(WATCHDOG, unset_env)
82
+ end
83
+
84
+ def self.fdstore(unset_env=false)
85
+ notify(FDSTORE, unset_env)
86
+ end
87
+
88
+ # @param [Boolean] true if the service manager expects watchdog keep-alive
89
+ # notification messages to be sent from this process.
90
+ #
91
+ # If the $WATCHDOG_USEC environment variable is set,
92
+ # and the $WATCHDOG_PID variable is unset or set to the PID of the current
93
+ # process
94
+ #
95
+ # @note Unlike sd_watchdog_enabled(3), this method does not mutate the
96
+ # environment.
97
+ def self.watchdog?
98
+ wd_usec = ENV["WATCHDOG_USEC"]
99
+ wd_pid = ENV["WATCHDOG_PID"]
100
+
101
+ return false if !wd_usec
102
+
103
+ begin
104
+ wd_usec = Integer(wd_usec)
105
+ rescue
106
+ return false
107
+ end
108
+
109
+ return false if wd_usec <= 0
110
+ return true if !wd_pid || wd_pid == $$.to_s
111
+
112
+ false
113
+ end
114
+
115
+ # Notify systemd with the provided state, via the notification socket, if
116
+ # any.
117
+ #
118
+ # Generally this method will be used indirectly through the other methods
119
+ # of the library.
120
+ #
121
+ # @param state [String]
122
+ # @param unset_env [Boolean]
123
+ #
124
+ # @return [Fixnum, nil] the number of bytes written to the notification
125
+ # socket or nil if there was no socket to report to (eg. the program wasn't
126
+ # started by systemd)
127
+ #
128
+ # @raise [NotifyError] if there was an error communicating with the systemd
129
+ # socket
130
+ #
131
+ # @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
132
+ def self.notify(state, unset_env=false)
133
+ sock = ENV["NOTIFY_SOCKET"]
134
+
135
+ return nil if !sock
136
+
137
+ ENV.delete("NOTIFY_SOCKET") if unset_env
138
+
139
+ begin
140
+ Addrinfo.unix(sock, :DGRAM).connect do |s|
141
+ s.close_on_exec = true
142
+ s.write(state)
143
+ end
144
+ rescue StandardError => e
145
+ raise NotifyError, "#{e.class}: #{e.message}", e.backtrace
146
+ end
147
+ end
148
+ end
149
+ end
data/lib/puma/server.rb CHANGED
@@ -11,12 +11,10 @@ require_relative 'reactor'
11
11
  require_relative 'client'
12
12
  require_relative 'binder'
13
13
  require_relative 'util'
14
- require_relative 'io_buffer'
15
14
  require_relative 'request'
16
15
 
17
16
  require 'socket'
18
17
  require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
19
- require 'forwardable'
20
18
 
21
19
  module Puma
22
20
 
@@ -33,7 +31,6 @@ module Puma
33
31
  class Server
34
32
  include Puma::Const
35
33
  include Request
36
- extend Forwardable
37
34
 
38
35
  attr_reader :thread
39
36
  attr_reader :log_writer
@@ -49,10 +46,7 @@ module Puma
49
46
  attr_accessor :app
50
47
  attr_accessor :binder
51
48
 
52
- def_delegators :@binder, :add_tcp_listener, :add_ssl_listener,
53
- :add_unix_listener, :connected_ports
54
-
55
- ThreadLocalKey = :puma_server
49
+ THREAD_LOCAL_KEY = :puma_server
56
50
 
57
51
  # Create a server for the rack app +app+.
58
52
  #
@@ -87,15 +81,29 @@ module Puma
87
81
  UserFileDefaultOptions.new(options, Configuration::DEFAULTS)
88
82
  end
89
83
 
90
- @log_writer = @options.fetch :log_writer, LogWriter.stdio
91
- @early_hints = @options[:early_hints]
92
- @first_data_timeout = @options[:first_data_timeout]
93
- @min_threads = @options[:min_threads]
94
- @max_threads = @options[:max_threads]
95
- @persistent_timeout = @options[:persistent_timeout]
96
- @queue_requests = @options[:queue_requests]
97
- @max_fast_inline = @options[:max_fast_inline]
98
- @io_selector_backend = @options[:io_selector_backend]
84
+ @log_writer = @options.fetch :log_writer, LogWriter.stdio
85
+ @early_hints = @options[:early_hints]
86
+ @first_data_timeout = @options[:first_data_timeout]
87
+ @persistent_timeout = @options[:persistent_timeout]
88
+ @idle_timeout = @options[:idle_timeout]
89
+ @min_threads = @options[:min_threads]
90
+ @max_threads = @options[:max_threads]
91
+ @queue_requests = @options[:queue_requests]
92
+ @max_fast_inline = @options[:max_fast_inline]
93
+ @io_selector_backend = @options[:io_selector_backend]
94
+ @http_content_length_limit = @options[:http_content_length_limit]
95
+
96
+ # make this a hash, since we prefer `key?` over `include?`
97
+ @supported_http_methods =
98
+ if @options[:supported_http_methods] == :any
99
+ :any
100
+ else
101
+ if (ary = @options[:supported_http_methods])
102
+ ary
103
+ else
104
+ SUPPORTED_HTTP_METHODS
105
+ end.sort.product([nil]).to_h.freeze
106
+ end
99
107
 
100
108
  temp = !!(@options[:environment] =~ /\A(development|test)\z/)
101
109
  @leak_stack_on_error = @options[:environment] ? temp : true
@@ -118,7 +126,7 @@ module Puma
118
126
  class << self
119
127
  # @!attribute [r] current
120
128
  def current
121
- Thread.current[ThreadLocalKey]
129
+ Thread.current[THREAD_LOCAL_KEY]
122
130
  end
123
131
 
124
132
  # :nodoc:
@@ -230,7 +238,7 @@ module Puma
230
238
 
231
239
  @status = :run
232
240
 
233
- @thread_pool = ThreadPool.new(thread_name, @options) { |a, b| process_client a, b }
241
+ @thread_pool = ThreadPool.new(thread_name, @options) { |client| process_client client }
234
242
 
235
243
  if @queue_requests
236
244
  @reactor = Reactor.new(@io_selector_backend) { |c| reactor_wakeup c }
@@ -318,8 +326,12 @@ module Puma
318
326
 
319
327
  while @status == :run || (drain && shutting_down?)
320
328
  begin
321
- ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : nil)
322
- break unless ios
329
+ ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : @idle_timeout)
330
+ unless ios
331
+ @status = :stop unless shutting_down?
332
+ break
333
+ end
334
+
323
335
  ios.first.each do |sock|
324
336
  if sock == check
325
337
  break if handle_check
@@ -335,6 +347,7 @@ module Puma
335
347
  drain += 1 if shutting_down?
336
348
  pool << Client.new(io, @binder.env(sock)).tap { |c|
337
349
  c.listener = sock
350
+ c.http_content_length_limit = @http_content_length_limit
338
351
  c.send(addr_send_name, addr_value) if addr_value
339
352
  }
340
353
  end
@@ -401,9 +414,9 @@ module Puma
401
414
  # returning.
402
415
  #
403
416
  # Return true if one or more requests were processed.
404
- def process_client(client, buffer)
417
+ def process_client(client)
405
418
  # Advertise this server into the thread
406
- Thread.current[ThreadLocalKey] = self
419
+ Thread.current[THREAD_LOCAL_KEY] = self
407
420
 
408
421
  clean_thread_locals = @options[:clean_thread_locals]
409
422
  close_socket = true
@@ -427,15 +440,13 @@ module Puma
427
440
 
428
441
  while true
429
442
  @requests_count += 1
430
- case handle_request(client, buffer, requests + 1)
443
+ case handle_request(client, requests + 1)
431
444
  when false
432
445
  break
433
446
  when :async
434
447
  close_socket = false
435
448
  break
436
449
  when true
437
- buffer.reset
438
-
439
450
  ThreadPool.clean_thread_locals if clean_thread_locals
440
451
 
441
452
  requests += 1
@@ -465,11 +476,11 @@ module Puma
465
476
  end
466
477
  true
467
478
  rescue StandardError => e
468
- client_error(e, client)
479
+ client_error(e, client, requests)
469
480
  # The ensure tries to close +client+ down
470
481
  requests > 0
471
482
  ensure
472
- buffer.reset
483
+ client.io_buffer.reset
473
484
 
474
485
  begin
475
486
  client.close if close_socket
@@ -493,22 +504,22 @@ module Puma
493
504
  # :nocov:
494
505
 
495
506
  # Handle various error types thrown by Client I/O operations.
496
- def client_error(e, client)
507
+ def client_error(e, client, requests = 1)
497
508
  # Swallow, do not log
498
509
  return if [ConnectionError, EOFError].include?(e.class)
499
510
 
500
- lowlevel_error(e, client.env)
501
511
  case e
502
512
  when MiniSSL::SSLError
513
+ lowlevel_error(e, client.env)
503
514
  @log_writer.ssl_error e, client.io
504
515
  when HttpParserError
505
- client.write_error(400)
516
+ response_to_error(client, requests, e, 400)
506
517
  @log_writer.parse_error e, client
507
518
  when HttpParserError501
508
- client.write_error(501)
519
+ response_to_error(client, requests, e, 501)
509
520
  @log_writer.parse_error e, client
510
521
  else
511
- client.write_error(500)
522
+ response_to_error(client, requests, e, 500)
512
523
  @log_writer.unknown_error e, nil, "Read"
513
524
  end
514
525
  end
@@ -530,10 +541,17 @@ module Puma
530
541
  backtrace = e.backtrace.nil? ? '<no backtrace available>' : e.backtrace.join("\n")
531
542
  [status, {}, ["Puma caught this error: #{e.message} (#{e.class})\n#{backtrace}"]]
532
543
  else
533
- [status, {}, ["An unhandled lowlevel error occurred. The application logs may have details.\n"]]
544
+ [status, {}, [""]]
534
545
  end
535
546
  end
536
547
 
548
+ def response_to_error(client, requests, err, status_code)
549
+ status, headers, res_body = lowlevel_error(err, client.env, status_code)
550
+ prepare_response(status, headers, res_body, requests, client)
551
+ client.write_error(status_code)
552
+ end
553
+ private :response_to_error
554
+
537
555
  # Wait for all outstanding requests to finish.
538
556
  #
539
557
  def graceful_shutdown
@@ -567,7 +585,7 @@ module Puma
567
585
 
568
586
  def notify_safely(message)
569
587
  @notify << message
570
- rescue IOError, NoMethodError, Errno::EPIPE
588
+ rescue IOError, NoMethodError, Errno::EPIPE, Errno::EBADF
571
589
  # The server, in another thread, is shutting down
572
590
  Puma::Util.purge_interrupt_queue
573
591
  rescue RuntimeError => e
@@ -612,5 +630,27 @@ module Puma
612
630
  def stats
613
631
  STAT_METHODS.map {|name| [name, send(name) || 0]}.to_h
614
632
  end
633
+
634
+ # below are 'delegations' to binder
635
+ # remove in Puma 7?
636
+
637
+
638
+ def add_tcp_listener(host, port, optimize_for_latency = true, backlog = 1024)
639
+ @binder.add_tcp_listener host, port, optimize_for_latency, backlog
640
+ end
641
+
642
+ def add_ssl_listener(host, port, ctx, optimize_for_latency = true,
643
+ backlog = 1024)
644
+ @binder.add_ssl_listener host, port, ctx, optimize_for_latency, backlog
645
+ end
646
+
647
+ def add_unix_listener(path, umask = nil, mode = nil, backlog = 1024)
648
+ @binder.add_unix_listener path, umask, mode, backlog
649
+ end
650
+
651
+ # @!attribute [r] connected_ports
652
+ def connected_ports
653
+ @binder.connected_ports
654
+ end
615
655
  end
616
656
  end
data/lib/puma/single.rb CHANGED
@@ -16,7 +16,7 @@ module Puma
16
16
  # @!attribute [r] stats
17
17
  def stats
18
18
  {
19
- started_at: @started_at.utc.iso8601
19
+ started_at: utc_iso8601(@started_at)
20
20
  }.merge(@server.stats).merge(super)
21
21
  end
22
22
 
@@ -57,6 +57,8 @@ module Puma
57
57
 
58
58
  @events.fire_on_booted!
59
59
 
60
+ debug_loaded_extensions("Loaded Extensions:") if @log_writer.debug?
61
+
60
62
  begin
61
63
  server_thread.join
62
64
  rescue Interrupt
File without changes
@@ -44,10 +44,15 @@ module Puma
44
44
  @name = name
45
45
  @min = Integer(options[:min_threads])
46
46
  @max = Integer(options[:max_threads])
47
+ # Not an 'exposed' option, options[:pool_shutdown_grace_time] is used in CI
48
+ # to shorten @shutdown_grace_time from SHUTDOWN_GRACE_TIME. Parallel CI
49
+ # makes stubbing constants difficult.
50
+ @shutdown_grace_time = Float(options[:pool_shutdown_grace_time] || SHUTDOWN_GRACE_TIME)
47
51
  @block = block
48
- @extra = [::Puma::IOBuffer]
49
52
  @out_of_band = options[:out_of_band]
50
53
  @clean_thread_locals = options[:clean_thread_locals]
54
+ @before_thread_start = options[:before_thread_start]
55
+ @before_thread_exit = options[:before_thread_exit]
51
56
  @reaping_time = options[:reaping_time]
52
57
  @auto_trim_time = options[:auto_trim_time]
53
58
 
@@ -104,6 +109,7 @@ module Puma
104
109
  def spawn_thread
105
110
  @spawned += 1
106
111
 
112
+ trigger_before_thread_start_hooks
107
113
  th = Thread.new(@spawned) do |spawned|
108
114
  Puma.set_thread_name '%s tp %03i' % [@name, spawned]
109
115
  todo = @todo
@@ -112,8 +118,6 @@ module Puma
112
118
  not_empty = @not_empty
113
119
  not_full = @not_full
114
120
 
115
- extra = @extra.map { |i| i.new }
116
-
117
121
  while true
118
122
  work = nil
119
123
 
@@ -124,6 +128,7 @@ module Puma
124
128
  @spawned -= 1
125
129
  @workers.delete th
126
130
  not_full.signal
131
+ trigger_before_thread_exit_hooks
127
132
  Thread.exit
128
133
  end
129
134
 
@@ -147,7 +152,7 @@ module Puma
147
152
  end
148
153
 
149
154
  begin
150
- @out_of_band_pending = true if block.call(work, *extra)
155
+ @out_of_band_pending = true if block.call(work)
151
156
  rescue Exception => e
152
157
  STDERR.puts "Error reached top of thread-pool: #{e.message} (#{e.class})"
153
158
  end
@@ -161,6 +166,36 @@ module Puma
161
166
 
162
167
  private :spawn_thread
163
168
 
169
+ def trigger_before_thread_start_hooks
170
+ return unless @before_thread_start&.any?
171
+
172
+ @before_thread_start.each do |b|
173
+ begin
174
+ b.call
175
+ rescue Exception => e
176
+ STDERR.puts "WARNING before_thread_start hook failed with exception (#{e.class}) #{e.message}"
177
+ end
178
+ end
179
+ nil
180
+ end
181
+
182
+ private :trigger_before_thread_start_hooks
183
+
184
+ def trigger_before_thread_exit_hooks
185
+ return unless @before_thread_exit&.any?
186
+
187
+ @before_thread_exit.each do |b|
188
+ begin
189
+ b.call
190
+ rescue Exception => e
191
+ STDERR.puts "WARNING before_thread_exit hook failed with exception (#{e.class}) #{e.message}"
192
+ end
193
+ end
194
+ nil
195
+ end
196
+
197
+ private :trigger_before_thread_exit_hooks
198
+
164
199
  # @version 5.0.0
165
200
  def trigger_out_of_band_hook
166
201
  return false unless @out_of_band&.any?
@@ -347,8 +382,8 @@ module Puma
347
382
 
348
383
  # Tell all threads in the pool to exit and wait for them to finish.
349
384
  # Wait +timeout+ seconds then raise +ForceShutdown+ in remaining threads.
350
- # Next, wait an extra +grace+ seconds then force-kill remaining threads.
351
- # Finally, wait +kill_grace+ seconds for remaining threads to exit.
385
+ # Next, wait an extra +@shutdown_grace_time+ seconds then force-kill remaining
386
+ # threads. Finally, wait 1 second for remaining threads to exit.
352
387
  #
353
388
  def shutdown(timeout=-1)
354
389
  threads = with_mutex do
@@ -385,7 +420,7 @@ module Puma
385
420
  t.raise ForceShutdown if t[:with_force_shutdown]
386
421
  end
387
422
  end
388
- join.call(SHUTDOWN_GRACE_TIME)
423
+ join.call(@shutdown_grace_time)
389
424
 
390
425
  # If threads are _still_ running, forcefully kill them and wait to finish.
391
426
  threads.each(&:kill)
data/lib/puma/util.rb CHANGED
File without changes
data/lib/puma.rb CHANGED
@@ -3,8 +3,6 @@
3
3
  # Standard libraries
4
4
  require 'socket'
5
5
  require 'tempfile'
6
- require 'time'
7
- require 'etc'
8
6
  require 'uri'
9
7
  require 'stringio'
10
8
 
@@ -28,7 +26,7 @@ module Puma
28
26
  # not in minissl.rb
29
27
  HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
30
28
 
31
- HAS_UNIX_SOCKET = Object.const_defined? :UNIXSocket
29
+ HAS_UNIX_SOCKET = Object.const_defined?(:UNIXSocket) && !IS_WINDOWS
32
30
 
33
31
  if HAS_SSL
34
32
  require_relative 'puma/minissl'