puma 7.0.4 → 8.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +162 -0
- data/README.md +25 -13
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/deployment.md +58 -23
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -0
- data/docs/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/jungle/README.md +1 -1
- data/docs/kubernetes.md +5 -12
- data/docs/plugins.md +2 -2
- data/docs/signals.md +10 -10
- data/docs/stats.md +2 -2
- data/docs/systemd.md +3 -3
- data/ext/puma_http11/http11_parser.java.rl +51 -65
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +168 -104
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
- data/ext/puma_http11/puma_http11.c +101 -109
- data/lib/puma/app/status.rb +10 -2
- data/lib/puma/binder.rb +2 -2
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/client.rb +138 -102
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster/worker.rb +10 -9
- data/lib/puma/cluster/worker_handle.rb +2 -2
- data/lib/puma/cluster.rb +12 -11
- data/lib/puma/cluster_accept_loop_delay.rb +17 -18
- data/lib/puma/configuration.rb +87 -17
- data/lib/puma/const.rb +4 -3
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +11 -0
- data/lib/puma/dsl.rb +115 -18
- data/lib/puma/launcher/bundle_pruner.rb +2 -4
- data/lib/puma/launcher.rb +35 -30
- data/lib/puma/log_writer.rb +8 -2
- data/lib/puma/reactor.rb +3 -12
- data/lib/puma/{request.rb → response.rb} +25 -194
- data/lib/puma/runner.rb +1 -1
- data/lib/puma/server.rb +103 -64
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/single.rb +2 -2
- data/lib/puma/state_file.rb +3 -2
- data/lib/puma/thread_pool.rb +139 -24
- data/lib/rack/handler/puma.rb +1 -1
- data/tools/Dockerfile +13 -5
- metadata +16 -5
- data/ext/puma_http11/ext_help.h +0 -15
data/lib/puma/dsl.rb
CHANGED
|
@@ -155,7 +155,7 @@ module Puma
|
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
def default_host
|
|
158
|
-
@options[:default_host] || Configuration
|
|
158
|
+
@options[:default_host] || Configuration.default_tcp_host
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
def inject(&blk)
|
|
@@ -216,6 +216,8 @@ module Puma
|
|
|
216
216
|
# activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
|
|
217
217
|
# @example
|
|
218
218
|
# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
|
|
219
|
+
# @example
|
|
220
|
+
# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true, data_only: true}
|
|
219
221
|
#
|
|
220
222
|
def activate_control_app(url="auto", opts={})
|
|
221
223
|
if url == "auto"
|
|
@@ -240,6 +242,7 @@ module Puma
|
|
|
240
242
|
|
|
241
243
|
@options[:control_auth_token] = auth_token
|
|
242
244
|
@options[:control_url_umask] = opts[:umask] if opts[:umask]
|
|
245
|
+
@options[:control_data_only] = opts[:data_only] if opts[:data_only]
|
|
243
246
|
end
|
|
244
247
|
|
|
245
248
|
# Load additional configuration from a file.
|
|
@@ -257,7 +260,8 @@ module Puma
|
|
|
257
260
|
# accepted protocols. Multiple urls can be bound to, calling +bind+ does
|
|
258
261
|
# not overwrite previous bindings.
|
|
259
262
|
#
|
|
260
|
-
# The default is "tcp://
|
|
263
|
+
# The default is "tcp://[::]:9292" when IPv6 interfaces are available,
|
|
264
|
+
# otherwise "tcp://0.0.0.0:9292".
|
|
261
265
|
#
|
|
262
266
|
# You can use query parameters within the url to specify options:
|
|
263
267
|
#
|
|
@@ -276,7 +280,7 @@ module Puma
|
|
|
276
280
|
# @example SSL cert for mutual TLS (mTLS)
|
|
277
281
|
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
|
|
278
282
|
# @example Disable optimization for low latency
|
|
279
|
-
# bind 'tcp://
|
|
283
|
+
# bind 'tcp://[::]:9292?low_latency=false'
|
|
280
284
|
# @example Socket permissions
|
|
281
285
|
# bind 'unix:///var/run/puma.sock?umask=0111'
|
|
282
286
|
#
|
|
@@ -346,7 +350,7 @@ module Puma
|
|
|
346
350
|
|
|
347
351
|
# Define how long persistent connections can be idle before Puma closes them.
|
|
348
352
|
#
|
|
349
|
-
# The default is
|
|
353
|
+
# The default is 65 seconds.
|
|
350
354
|
#
|
|
351
355
|
# @example
|
|
352
356
|
# persistent_timeout 30
|
|
@@ -592,6 +596,29 @@ module Puma
|
|
|
592
596
|
@options[:max_threads] = max
|
|
593
597
|
end
|
|
594
598
|
|
|
599
|
+
# Configure the max number of IO threads.
|
|
600
|
+
#
|
|
601
|
+
# When request handlers know the current requests will no longer use a significant amount
|
|
602
|
+
# of CPU, they can mark the current request as IO bound using <tt>env["puma.mark_as_io_bound"]</tt>.
|
|
603
|
+
#
|
|
604
|
+
# Threads marked as IO bound are allowed to go over the max thread limit.
|
|
605
|
+
#
|
|
606
|
+
# @example
|
|
607
|
+
# threads 5
|
|
608
|
+
# max_io_threads 5
|
|
609
|
+
#
|
|
610
|
+
# The above example allows for 5 regular threads and 5 IO threads to process requests concurrently.
|
|
611
|
+
# Any IO thread over the limit is counted as a regular thread, hence the above configuration also
|
|
612
|
+
# allows for 3 regular threads and 7 IO threads for example.
|
|
613
|
+
def max_io_threads(max)
|
|
614
|
+
max = Integer(max)
|
|
615
|
+
if max < 0
|
|
616
|
+
raise "The maximum number of IO threads (#{max}) must be a positive number"
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
@options[:max_io_threads] = max
|
|
620
|
+
end
|
|
621
|
+
|
|
595
622
|
# Instead of using +bind+ and manually constructing a URI like:
|
|
596
623
|
#
|
|
597
624
|
# bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
|
|
@@ -656,7 +683,8 @@ module Puma
|
|
|
656
683
|
@options[:state] = path.to_s
|
|
657
684
|
end
|
|
658
685
|
|
|
659
|
-
# Use +permission+ to restrict permissions for the state file.
|
|
686
|
+
# Use +permission+ to restrict permissions for the state file. By convention,
|
|
687
|
+
# +permission+ is an octal number (e.g. `0640` or `0o640`).
|
|
660
688
|
#
|
|
661
689
|
# @example
|
|
662
690
|
# state_permission 0600
|
|
@@ -665,21 +693,27 @@ module Puma
|
|
|
665
693
|
@options[:state_permission] = permission
|
|
666
694
|
end
|
|
667
695
|
|
|
668
|
-
# How many worker processes to run.
|
|
669
|
-
#
|
|
696
|
+
# How many worker processes to run. Typically this is set to the number of
|
|
697
|
+
# available cores.
|
|
670
698
|
#
|
|
671
699
|
# The default is the value of the environment variable +WEB_CONCURRENCY+ if
|
|
672
|
-
# set, otherwise 0.
|
|
700
|
+
# set, otherwise 0. Passing +:auto+ will set the value to
|
|
701
|
+
# +Concurrent.available_processor_count+ (requires the concurrent-ruby gem).
|
|
702
|
+
# On some platforms (e.g. under CPU quotas) this may be fractional, and Puma
|
|
703
|
+
# will round down. If it rounds down to 0, Puma will run in single mode and
|
|
704
|
+
# cluster-only hooks like +before_worker_boot+ will not execute.
|
|
705
|
+
# If you rely on cluster-only hooks, set an explicit worker count.
|
|
673
706
|
#
|
|
674
|
-
#
|
|
707
|
+
# A value of 0 or nil means run in single mode.
|
|
675
708
|
#
|
|
676
709
|
# @example
|
|
677
710
|
# workers 2
|
|
711
|
+
# workers :auto
|
|
678
712
|
#
|
|
679
713
|
# @see Puma::Cluster
|
|
680
714
|
#
|
|
681
715
|
def workers(count)
|
|
682
|
-
@options[:workers] = count.
|
|
716
|
+
@options[:workers] = count.nil? ? 0 : @config.send(:parse_workers, count)
|
|
683
717
|
end
|
|
684
718
|
|
|
685
719
|
# Disable warning message when running in cluster mode with a single worker.
|
|
@@ -717,6 +751,44 @@ module Puma
|
|
|
717
751
|
@options[:silence_fork_callback_warning] = true
|
|
718
752
|
end
|
|
719
753
|
|
|
754
|
+
# Code to run only in single mode.
|
|
755
|
+
# Runs after all config files are loaded.
|
|
756
|
+
#
|
|
757
|
+
# This can be called multiple times.
|
|
758
|
+
#
|
|
759
|
+
# @note Single mode only.
|
|
760
|
+
#
|
|
761
|
+
# @example
|
|
762
|
+
# single do
|
|
763
|
+
# silence_fork_callback_warning
|
|
764
|
+
# end
|
|
765
|
+
#
|
|
766
|
+
def single(&block)
|
|
767
|
+
raise ArgumentError, "A block must be provided to `single`" unless block
|
|
768
|
+
|
|
769
|
+
@options[:single] ||= []
|
|
770
|
+
@options[:single] << block
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
# Code to run only in cluster mode.
|
|
774
|
+
# Runs after all config files are loaded.
|
|
775
|
+
#
|
|
776
|
+
# This can be called multiple times.
|
|
777
|
+
#
|
|
778
|
+
# @note Cluster mode only.
|
|
779
|
+
#
|
|
780
|
+
# @example
|
|
781
|
+
# cluster do
|
|
782
|
+
# prune_bundler
|
|
783
|
+
# end
|
|
784
|
+
#
|
|
785
|
+
def cluster(&block)
|
|
786
|
+
raise ArgumentError, "A block must be provided to `cluster`" unless block
|
|
787
|
+
|
|
788
|
+
@options[:cluster] ||= []
|
|
789
|
+
@options[:cluster] << block
|
|
790
|
+
end
|
|
791
|
+
|
|
720
792
|
# Code to run immediately before master process
|
|
721
793
|
# forks workers (once on boot). These hooks can block if necessary
|
|
722
794
|
# to wait for background operations unknown to Puma to finish before
|
|
@@ -818,6 +890,20 @@ module Puma
|
|
|
818
890
|
|
|
819
891
|
alias_method :after_worker_boot, :after_worker_fork
|
|
820
892
|
|
|
893
|
+
# Code to run in the master right after a worker has stopped. The worker's
|
|
894
|
+
# index and Process::Status are passed as arguments.
|
|
895
|
+
#
|
|
896
|
+
# @note Cluster mode only.
|
|
897
|
+
#
|
|
898
|
+
# @example
|
|
899
|
+
# after_worker_shutdown do |worker_handle|
|
|
900
|
+
# puts 'Worker crashed' unless worker_handle.process_status.success?
|
|
901
|
+
# end
|
|
902
|
+
#
|
|
903
|
+
def after_worker_shutdown(&block)
|
|
904
|
+
process_hook :after_worker_shutdown, nil, block, cluster_only: true
|
|
905
|
+
end
|
|
906
|
+
|
|
821
907
|
# Code to run after puma is booted (works for both single and cluster modes).
|
|
822
908
|
#
|
|
823
909
|
# @example
|
|
@@ -980,6 +1066,7 @@ module Puma
|
|
|
980
1066
|
# The default is +true+ if your app uses more than 1 worker.
|
|
981
1067
|
#
|
|
982
1068
|
# @note Cluster mode only.
|
|
1069
|
+
# @note When using `fork_worker`, this only applies to worker 0.
|
|
983
1070
|
#
|
|
984
1071
|
# @example
|
|
985
1072
|
# preload_app!
|
|
@@ -1015,6 +1102,7 @@ module Puma
|
|
|
1015
1102
|
# new Bundler context and thus can float around as the release
|
|
1016
1103
|
# dictates.
|
|
1017
1104
|
#
|
|
1105
|
+
# @note Cluster mode only.
|
|
1018
1106
|
# @note This is incompatible with +preload_app!+.
|
|
1019
1107
|
# @note This is only supported for RubyGems 2.2+
|
|
1020
1108
|
#
|
|
@@ -1120,7 +1208,7 @@ module Puma
|
|
|
1120
1208
|
|
|
1121
1209
|
# Change the default worker timeout for booting.
|
|
1122
1210
|
#
|
|
1123
|
-
# The default is
|
|
1211
|
+
# The default is 60 seconds.
|
|
1124
1212
|
#
|
|
1125
1213
|
# @note Cluster mode only.
|
|
1126
1214
|
#
|
|
@@ -1202,18 +1290,27 @@ module Puma
|
|
|
1202
1290
|
# threads will be written to $stdout. This can help figure
|
|
1203
1291
|
# out why shutdown is hanging.
|
|
1204
1292
|
#
|
|
1205
|
-
|
|
1206
|
-
|
|
1293
|
+
# If `on_force` is true, the backtraces will be written only
|
|
1294
|
+
# when the shutdown is forced i.e. not graceful.
|
|
1295
|
+
#
|
|
1296
|
+
# @see force_shutdown_after
|
|
1297
|
+
def shutdown_debug(val = true, on_force: false)
|
|
1298
|
+
@options[:shutdown_debug] = val && on_force ? :on_force : val
|
|
1207
1299
|
end
|
|
1208
1300
|
|
|
1209
|
-
|
|
1210
|
-
#
|
|
1211
|
-
#
|
|
1301
|
+
# Maximum delay of worker accept loop.
|
|
1302
|
+
#
|
|
1303
|
+
# Attempts to route traffic to less-busy workers by causing a busy worker to delay
|
|
1304
|
+
# listening on the socket, allowing workers which are not processing as many
|
|
1212
1305
|
# requests to pick up new requests first.
|
|
1213
1306
|
#
|
|
1214
1307
|
# The default is 0.005 seconds.
|
|
1215
1308
|
#
|
|
1216
|
-
#
|
|
1309
|
+
# To turn off this feature, set the value to 0.
|
|
1310
|
+
#
|
|
1311
|
+
# @note Cluster mode with >= 2 workers only.
|
|
1312
|
+
#
|
|
1313
|
+
# @note Interpreters with forking support only.
|
|
1217
1314
|
#
|
|
1218
1315
|
# @see Puma::Server#handle_servers
|
|
1219
1316
|
# @see Puma::ThreadPool#wait_for_less_busy_worker
|
|
@@ -1357,7 +1454,7 @@ module Puma
|
|
|
1357
1454
|
#
|
|
1358
1455
|
# The default is +:auto+.
|
|
1359
1456
|
#
|
|
1360
|
-
# @see https://github.com/socketry/nio4r/blob/
|
|
1457
|
+
# @see https://github.com/socketry/nio4r/blob/main/lib/nio/selector.rb
|
|
1361
1458
|
#
|
|
1362
1459
|
def io_selector_backend(backend)
|
|
1363
1460
|
@options[:io_selector_backend] = backend.to_sym
|
|
@@ -28,14 +28,12 @@ module Puma
|
|
|
28
28
|
|
|
29
29
|
log '* Pruning Bundler environment'
|
|
30
30
|
home = ENV['GEM_HOME']
|
|
31
|
-
|
|
32
|
-
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
|
31
|
+
original_bundle_env = Bundler.original_env.select { |k, v| k.start_with?('BUNDLE_') && v }
|
|
33
32
|
|
|
34
33
|
with_unbundled_env do
|
|
35
34
|
ENV['GEM_HOME'] = home
|
|
36
|
-
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
|
37
35
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
|
38
|
-
ENV[
|
|
36
|
+
original_bundle_env.each { |k, v| ENV[k] = v }
|
|
39
37
|
args = [Gem.ruby, puma_wild_path, '-I', dirs.join(':')] + @original_argv
|
|
40
38
|
# Defaults to true which breaks socket activation
|
|
41
39
|
args += [{:close_others => false}]
|
data/lib/puma/launcher.rb
CHANGED
|
@@ -42,26 +42,40 @@ module Puma
|
|
|
42
42
|
# end
|
|
43
43
|
# Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
|
|
44
44
|
def initialize(conf, launcher_args={})
|
|
45
|
-
|
|
46
|
-
@log_writer = launcher_args[:log_writer] || LogWriter::DEFAULT
|
|
47
|
-
@events = launcher_args[:events] || Events.new
|
|
48
|
-
@argv = launcher_args[:argv] || []
|
|
49
|
-
@original_argv = @argv.dup
|
|
50
|
-
@config = conf
|
|
51
|
-
|
|
52
|
-
env = launcher_args.delete(:env) || ENV
|
|
45
|
+
## Minimal initialization before potential early restart (e.g. from bundle pruning)
|
|
53
46
|
|
|
47
|
+
@config = conf
|
|
48
|
+
# Advertise the CLI Configuration before config files are loaded
|
|
49
|
+
Puma.cli_config = @config if defined?(Puma.cli_config)
|
|
54
50
|
@config.clamp
|
|
51
|
+
|
|
55
52
|
@options = @config.options
|
|
56
53
|
|
|
54
|
+
@log_writer = launcher_args[:log_writer] || LogWriter::DEFAULT
|
|
55
|
+
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
|
|
56
|
+
@log_writer.formatter = @options[:log_formatter] if @options[:log_formatter]
|
|
57
|
+
@log_writer.custom_logger = @options[:custom_logger] if @options[:custom_logger]
|
|
57
58
|
@options[:log_writer] = @log_writer
|
|
58
59
|
@options[:logger] = @log_writer if clustered?
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
@events = launcher_args[:events] || Events.new
|
|
62
|
+
|
|
63
|
+
@argv = launcher_args[:argv] || []
|
|
64
|
+
@original_argv = @argv.dup
|
|
65
|
+
|
|
66
|
+
## End minimal initialization
|
|
67
|
+
|
|
68
|
+
generate_restart_data
|
|
69
|
+
Dir.chdir(@restart_dir)
|
|
70
|
+
|
|
71
|
+
prune_bundler!
|
|
72
|
+
|
|
73
|
+
env = launcher_args.delete(:env) || ENV
|
|
74
|
+
|
|
75
|
+
# Log after prune_bundler! to avoid duplicate logging if a restart occurs
|
|
62
76
|
log_config if env['PUMA_LOG_CONFIG']
|
|
63
77
|
|
|
64
|
-
@binder
|
|
78
|
+
@binder = Binder.new(@log_writer, @options)
|
|
65
79
|
@binder.create_inherited_fds(env).each { |k| env.delete k }
|
|
66
80
|
@binder.create_activated_fds(env).each { |k| env.delete k }
|
|
67
81
|
|
|
@@ -81,21 +95,10 @@ module Puma
|
|
|
81
95
|
)
|
|
82
96
|
end
|
|
83
97
|
|
|
84
|
-
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
|
|
85
|
-
@log_writer.formatter = @options[:log_formatter] if @options[:log_formatter]
|
|
86
|
-
|
|
87
|
-
@log_writer.custom_logger = @options[:custom_logger] if @options[:custom_logger]
|
|
88
|
-
|
|
89
|
-
generate_restart_data
|
|
90
|
-
|
|
91
98
|
if clustered? && !Puma.forkable?
|
|
92
99
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
|
93
100
|
end
|
|
94
101
|
|
|
95
|
-
Dir.chdir(@restart_dir)
|
|
96
|
-
|
|
97
|
-
prune_bundler!
|
|
98
|
-
|
|
99
102
|
@environment = @options[:environment] if @options[:environment]
|
|
100
103
|
set_rack_environment
|
|
101
104
|
|
|
@@ -139,7 +142,10 @@ module Puma
|
|
|
139
142
|
# Delete the configured pidfile
|
|
140
143
|
def delete_pidfile
|
|
141
144
|
path = @options[:pidfile]
|
|
142
|
-
|
|
145
|
+
begin
|
|
146
|
+
File.unlink(path) if path
|
|
147
|
+
rescue Errno::ENOENT
|
|
148
|
+
end
|
|
143
149
|
end
|
|
144
150
|
|
|
145
151
|
# Begin async shutdown of the server
|
|
@@ -381,9 +387,9 @@ module Puma
|
|
|
381
387
|
# using it.
|
|
382
388
|
@restart_dir = Dir.pwd
|
|
383
389
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
390
|
+
# Use the same trick as unicorn, namely favor PWD because
|
|
391
|
+
# it will contain an unresolved symlink, useful for when
|
|
392
|
+
# the pwd is /data/releases/current.
|
|
387
393
|
elsif dir = ENV['PWD']
|
|
388
394
|
s_env = File.stat(dir)
|
|
389
395
|
s_pwd = File.stat(Dir.pwd)
|
|
@@ -470,8 +476,8 @@ module Puma
|
|
|
470
476
|
end
|
|
471
477
|
|
|
472
478
|
begin
|
|
473
|
-
|
|
474
|
-
Signal.trap
|
|
479
|
+
if Puma.backtrace_signal
|
|
480
|
+
Signal.trap Puma.backtrace_signal do
|
|
475
481
|
thread_status do |name, backtrace|
|
|
476
482
|
@log_writer.log(name)
|
|
477
483
|
@log_writer.log(backtrace.map { |bt| " #{bt}" })
|
|
@@ -479,8 +485,7 @@ module Puma
|
|
|
479
485
|
end
|
|
480
486
|
end
|
|
481
487
|
rescue Exception
|
|
482
|
-
|
|
483
|
-
# to see this constantly on Linux.
|
|
488
|
+
log "*** SIGINFO/SIGPWR not implemented, signal based backtrace unavailable!"
|
|
484
489
|
end
|
|
485
490
|
end
|
|
486
491
|
|
data/lib/puma/log_writer.rb
CHANGED
|
@@ -90,8 +90,14 @@ module Puma
|
|
|
90
90
|
@debug
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
def debug(str)
|
|
94
|
-
|
|
93
|
+
def debug(str=nil, &block)
|
|
94
|
+
if @debug
|
|
95
|
+
if block_given?
|
|
96
|
+
log("% #{yield}")
|
|
97
|
+
else
|
|
98
|
+
log("% #{str}")
|
|
99
|
+
end
|
|
100
|
+
end
|
|
95
101
|
end
|
|
96
102
|
|
|
97
103
|
# Write +str+ to +@stderr+
|
data/lib/puma/reactor.rb
CHANGED
|
@@ -75,15 +75,12 @@ module Puma
|
|
|
75
75
|
private
|
|
76
76
|
|
|
77
77
|
def select_loop
|
|
78
|
-
close_selector = true
|
|
79
78
|
begin
|
|
80
79
|
until @input.closed? && @input.empty?
|
|
81
80
|
# Wakeup any registered object that receives incoming data.
|
|
82
81
|
# Block until the earliest timeout or Selector#wakeup is called.
|
|
83
82
|
timeout = (earliest = @timeouts.first) && earliest.timeout
|
|
84
|
-
monitor_wake_up = false
|
|
85
83
|
@selector.select(timeout) do |monitor|
|
|
86
|
-
monitor_wake_up = true
|
|
87
84
|
wakeup!(monitor.value)
|
|
88
85
|
end
|
|
89
86
|
|
|
@@ -103,18 +100,12 @@ module Puma
|
|
|
103
100
|
STDERR.puts "Error in reactor loop escaped: #{e.message} (#{e.class})"
|
|
104
101
|
STDERR.puts e.backtrace
|
|
105
102
|
|
|
106
|
-
|
|
107
|
-
# is odd. Regardless, it may continue for thousands of calls if retried.
|
|
108
|
-
# Also, when it raises, @selector.close also raises an error.
|
|
109
|
-
if !monitor_wake_up && NoMethodError === e
|
|
110
|
-
close_selector = false
|
|
111
|
-
else
|
|
112
|
-
retry
|
|
113
|
-
end
|
|
103
|
+
retry
|
|
114
104
|
end
|
|
105
|
+
|
|
115
106
|
# Wakeup all remaining objects on shutdown.
|
|
116
107
|
@timeouts.each(&@block)
|
|
117
|
-
@selector.close
|
|
108
|
+
@selector.close
|
|
118
109
|
end
|
|
119
110
|
|
|
120
111
|
# Start monitoring the object.
|