puma 7.0.0.pre1-java → 7.0.1-java

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.
data/lib/puma/request.rb CHANGED
@@ -52,6 +52,7 @@ module Puma
52
52
  io_buffer = client.io_buffer
53
53
  socket = client.io # io may be a MiniSSL::Socket
54
54
  app_body = nil
55
+ error = nil
55
56
 
56
57
  return false if closed_socket?(socket)
57
58
 
@@ -68,7 +69,7 @@ module Puma
68
69
  end
69
70
 
70
71
  env[HIJACK_P] = true
71
- env[HIJACK] = client
72
+ env[HIJACK] = client.method :full_hijack
72
73
 
73
74
  env[RACK_INPUT] = client.body
74
75
  env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
@@ -92,6 +93,7 @@ module Puma
92
93
  # array, we will invoke them when the request is done.
93
94
  #
94
95
  env[RACK_AFTER_REPLY] ||= []
96
+ env[RACK_RESPONSE_FINISHED] ||= []
95
97
 
96
98
  begin
97
99
  if @supported_http_methods == :any || @supported_http_methods.key?(env[REQUEST_METHOD])
@@ -119,15 +121,15 @@ module Puma
119
121
 
120
122
  return :async
121
123
  end
122
- rescue ThreadPool::ForceShutdown => e
123
- @log_writer.unknown_error e, client, "Rack app"
124
+ rescue ThreadPool::ForceShutdown => error
125
+ @log_writer.unknown_error error, client, "Rack app"
124
126
  @log_writer.log "Detected force shutdown of a thread"
125
127
 
126
- status, headers, res_body = lowlevel_error(e, env, 503)
127
- rescue Exception => e
128
- @log_writer.unknown_error e, client, "Rack app"
128
+ status, headers, res_body = lowlevel_error(error, env, 503)
129
+ rescue Exception => error
130
+ @log_writer.unknown_error error, client, "Rack app"
129
131
 
130
- status, headers, res_body = lowlevel_error(e, env, 500)
132
+ status, headers, res_body = lowlevel_error(error, env, 500)
131
133
  end
132
134
  prepare_response(status, headers, res_body, requests, client)
133
135
  ensure
@@ -144,6 +146,16 @@ module Puma
144
146
  end
145
147
  end
146
148
  end
149
+
150
+ if response_finished = env[RACK_RESPONSE_FINISHED]
151
+ response_finished.reverse_each do |o|
152
+ begin
153
+ o.call(env, status, headers, error)
154
+ rescue StandardError => e
155
+ @log_writer.debug_error e
156
+ end
157
+ end
158
+ end
147
159
  end
148
160
 
149
161
  # Assembles the headers and prepares the body for actually sending the
@@ -469,7 +481,7 @@ module Puma
469
481
 
470
482
  # The legacy HTTP_VERSION header can be sent as a client header.
471
483
  # Rack v4 may remove using HTTP_VERSION. If so, remove this line.
472
- env[HTTP_VERSION] = env[SERVER_PROTOCOL]
484
+ env[HTTP_VERSION] = env[SERVER_PROTOCOL] if @env_set_http_version
473
485
  end
474
486
  private :normalize_env
475
487
 
@@ -659,10 +671,10 @@ module Puma
659
671
  if ary
660
672
  ary.each do |v|
661
673
  next if illegal_header_value?(v)
662
- io_buffer.append k, colon, v, line_ending
674
+ io_buffer.append k.downcase, colon, v, line_ending
663
675
  end
664
676
  else
665
- io_buffer.append k, colon, line_ending
677
+ io_buffer.append k.downcase, colon, line_ending
666
678
  end
667
679
  end
668
680
 
data/lib/puma/runner.rb CHANGED
@@ -33,7 +33,6 @@ module Puma
33
33
  @wakeup.write PIPE_WAKEUP unless @wakeup.closed?
34
34
 
35
35
  rescue SystemCallError, IOError
36
- Puma::Util.purge_interrupt_queue
37
36
  end
38
37
 
39
38
  def development?
@@ -93,22 +92,6 @@ module Puma
93
92
  @control.binder.close_listeners if @control
94
93
  end
95
94
 
96
- # @!attribute [r] ruby_engine
97
- # @deprecated Use `RUBY_DESCRIPTION` instead
98
- def ruby_engine
99
- warn "Puma::Runner#ruby_engine is deprecated; use RUBY_DESCRIPTION instead. It will be removed in puma v7."
100
-
101
- if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
102
- "ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
103
- else
104
- if defined?(RUBY_ENGINE_VERSION)
105
- "#{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} - ruby #{RUBY_VERSION}"
106
- else
107
- "#{RUBY_ENGINE} #{RUBY_VERSION}"
108
- end
109
- end
110
- end
111
-
112
95
  def output_header(mode)
113
96
  min_t = @options[:min_threads]
114
97
  max_t = @options[:max_threads]
@@ -128,6 +111,14 @@ module Puma
128
111
  end
129
112
  end
130
113
 
114
+ def warn_ruby_mn_threads
115
+ return if !ENV.key?('RUBY_MN_THREADS')
116
+
117
+ log "! WARNING: Detected `RUBY_MN_THREADS=#{ENV['RUBY_MN_THREADS']}`"
118
+ log "! This setting is known to cause performance regressions with Puma."
119
+ log "! Consider disabling this environment variable: https://github.com/puma/puma/issues/3720"
120
+ end
121
+
131
122
  def redirected_io?
132
123
  @options[:redirect_stdout] || @options[:redirect_stderr]
133
124
  end
data/lib/puma/server.rb CHANGED
@@ -12,14 +12,14 @@ require_relative 'client'
12
12
  require_relative 'binder'
13
13
  require_relative 'util'
14
14
  require_relative 'request'
15
+ require_relative 'configuration'
15
16
 
16
17
  require 'socket'
17
18
  require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
18
19
 
19
20
  module Puma
20
-
21
- # This method was private on Ruby 2.4 but became public on Ruby 2.5+:
22
- Thread.send(:attr_accessor, :puma_server)
21
+ # Add `Thread#puma_server` and `Thread#puma_server=`
22
+ Thread.attr_accessor(:puma_server)
23
23
 
24
24
  # The HTTP Server itself. Serves out a single Rack app.
25
25
  #
@@ -32,6 +32,14 @@ module Puma
32
32
  #
33
33
  # Each `Puma::Server` will have one reactor and one thread pool.
34
34
  class Server
35
+ module FiberPerRequest
36
+ def handle_request(client, requests)
37
+ Fiber.new do
38
+ super
39
+ end.resume
40
+ end
41
+ end
42
+
35
43
  include Puma::Const
36
44
  include Request
37
45
 
@@ -77,6 +85,9 @@ module Puma
77
85
 
78
86
  @thread = nil
79
87
  @thread_pool = nil
88
+ @reactor = nil
89
+
90
+ @env_set_http_version = nil
80
91
 
81
92
  @options = if options.is_a?(UserFileDefaultOptions)
82
93
  options
@@ -100,6 +111,10 @@ module Puma
100
111
  @io_selector_backend = @options[:io_selector_backend]
101
112
  @http_content_length_limit = @options[:http_content_length_limit]
102
113
 
114
+ if @options[:fiber_per_request]
115
+ singleton_class.prepend(FiberPerRequest)
116
+ end
117
+
103
118
  # make this a hash, since we prefer `key?` over `include?`
104
119
  @supported_http_methods =
105
120
  if @options[:supported_http_methods] == :any
@@ -115,7 +130,7 @@ module Puma
115
130
  temp = !!(@options[:environment] =~ /\A(development|test)\z/)
116
131
  @leak_stack_on_error = @options[:environment] ? temp : true
117
132
 
118
- @binder = Binder.new(log_writer)
133
+ @binder = Binder.new(log_writer, @options)
119
134
 
120
135
  ENV['RACK_ENV'] ||= "development"
121
136
 
@@ -166,7 +181,6 @@ module Puma
166
181
  begin
167
182
  skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 1) if skt.kind_of? TCPSocket
168
183
  rescue IOError, SystemCallError
169
- Puma::Util.purge_interrupt_queue
170
184
  end
171
185
  end
172
186
 
@@ -175,7 +189,6 @@ module Puma
175
189
  begin
176
190
  skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 0) if skt.kind_of? TCPSocket
177
191
  rescue IOError, SystemCallError
178
- Puma::Util.purge_interrupt_queue
179
192
  end
180
193
  end
181
194
  else
@@ -196,7 +209,6 @@ module Puma
196
209
  begin
197
210
  tcp_info = skt.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_INFO)
198
211
  rescue IOError, SystemCallError
199
- Puma::Util.purge_interrupt_queue
200
212
  @precheck_closing = false
201
213
  false
202
214
  else
@@ -318,6 +330,9 @@ module Puma
318
330
  end
319
331
 
320
332
  def handle_servers
333
+ @env_set_http_version = Object.const_defined?(:Rack) && ::Rack.respond_to?(:release) &&
334
+ Gem::Version.new(::Rack.release) < Gem::Version.new('3.1.0')
335
+
321
336
  begin
322
337
  check = @check
323
338
  sockets = [check] + @binder.ios
@@ -460,7 +475,6 @@ module Puma
460
475
  # Advertise this server into the thread
461
476
  Thread.current.puma_server = self
462
477
 
463
- clean_thread_locals = options[:clean_thread_locals]
464
478
  close_socket = true
465
479
 
466
480
  requests = 0
@@ -485,8 +499,6 @@ module Puma
485
499
  when :async
486
500
  close_socket = false
487
501
  when true
488
- ThreadPool.clean_thread_locals if clean_thread_locals
489
-
490
502
  requests += 1
491
503
 
492
504
  client.reset
@@ -520,7 +532,6 @@ module Puma
520
532
  begin
521
533
  client.close if close_socket
522
534
  rescue IOError, SystemCallError
523
- Puma::Util.purge_interrupt_queue
524
535
  # Already closed
525
536
  rescue StandardError => e
526
537
  @log_writer.unknown_error e, nil, "Client"
@@ -621,11 +632,10 @@ module Puma
621
632
  @notify << message
622
633
  rescue IOError, NoMethodError, Errno::EPIPE, Errno::EBADF
623
634
  # The server, in another thread, is shutting down
624
- Puma::Util.purge_interrupt_queue
625
635
  rescue RuntimeError => e
626
636
  # Temporary workaround for https://bugs.ruby-lang.org/issues/13239
627
637
  if e.message.include?('IOError')
628
- Puma::Util.purge_interrupt_queue
638
+ # ignore
629
639
  else
630
640
  raise e
631
641
  end
data/lib/puma/single.rb CHANGED
@@ -53,9 +53,12 @@ module Puma
53
53
  server_thread = server.run
54
54
 
55
55
  log "Use Ctrl-C to stop"
56
+
57
+ warn_ruby_mn_threads
58
+
56
59
  redirect_io
57
60
 
58
- @events.fire_on_booted!
61
+ @events.fire_after_booted!
59
62
 
60
63
  debug_loaded_extensions("Loaded Extensions:") if @log_writer.debug?
61
64
 
@@ -53,7 +53,6 @@ module Puma
53
53
  @block = block
54
54
  @out_of_band = options[:out_of_band]
55
55
  @out_of_band_running = false
56
- @clean_thread_locals = options[:clean_thread_locals]
57
56
  @before_thread_start = options[:before_thread_start]
58
57
  @before_thread_exit = options[:before_thread_exit]
59
58
  @reaping_time = options[:reaping_time]
@@ -82,12 +81,6 @@ module Puma
82
81
 
83
82
  attr_reader :spawned, :trim_requested, :waiting
84
83
 
85
- def self.clean_thread_locals
86
- Thread.current.keys.each do |key| # rubocop: disable Style/HashEachMethods
87
- Thread.current[key] = nil unless key == :__recursive_key__
88
- end
89
- end
90
-
91
84
  # generate stats hash so as not to perform multiple locks
92
85
  # @return [Hash] hash containing stat info from ThreadPool
93
86
  def stats
@@ -175,10 +168,6 @@ module Puma
175
168
  work = todo.shift
176
169
  end
177
170
 
178
- if @clean_thread_locals
179
- ThreadPool.clean_thread_locals
180
- end
181
-
182
171
  begin
183
172
  @out_of_band_pending = true if block.call(work)
184
173
  rescue Exception => e
@@ -199,7 +188,7 @@ module Puma
199
188
 
200
189
  @before_thread_start.each do |b|
201
190
  begin
202
- b.call
191
+ b[:block].call
203
192
  rescue Exception => e
204
193
  STDERR.puts "WARNING before_thread_start hook failed with exception (#{e.class}) #{e.message}"
205
194
  end
@@ -214,7 +203,7 @@ module Puma
214
203
 
215
204
  @before_thread_exit.each do |b|
216
205
  begin
217
- b.call
206
+ b[:block].call
218
207
  rescue Exception => e
219
208
  STDERR.puts "WARNING before_thread_exit hook failed with exception (#{e.class}) #{e.message}"
220
209
  end
@@ -231,7 +220,7 @@ module Puma
231
220
  # we execute on idle hook when all threads are free
232
221
  return false unless @spawned == @waiting
233
222
  @out_of_band_running = true
234
- @out_of_band.each(&:call)
223
+ @out_of_band.each { |b| b[:block].call }
235
224
  true
236
225
  rescue Exception => e
237
226
  STDERR.puts "Exception calling out_of_band_hook: #{e.message} (#{e.class})"
data/lib/puma/util.rb CHANGED
@@ -10,13 +10,6 @@ module Puma
10
10
  IO.pipe
11
11
  end
12
12
 
13
- # An instance method on Thread has been provided to address https://bugs.ruby-lang.org/issues/13632,
14
- # which currently affects some older versions of Ruby: 2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1
15
- # Additional context: https://github.com/puma/puma/pull/1345
16
- def purge_interrupt_queue
17
- Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
18
- end
19
-
20
13
  # Escapes and unescapes a URI escaped string with
21
14
  # +encoding+. +encoding+ will be the target encoding of the string
22
15
  # returned, and it defaults to UTF-8
data/lib/puma.rb CHANGED
@@ -75,4 +75,14 @@ module Puma
75
75
  def self.set_thread_name(name)
76
76
  Thread.current.name = "puma #{name}"
77
77
  end
78
+
79
+ # Shows deprecated warning for renamed methods.
80
+ # @example
81
+ # Puma.deprecate_method_change :on_booted, __callee__, __method__
82
+ #
83
+ def self.deprecate_method_change(method_old, method_caller, method_new)
84
+ if method_old == method_caller
85
+ warn "Use '#{method_new}', '#{method_caller}' is deprecated and will be removed in v8"
86
+ end
87
+ end
78
88
  end
@@ -32,7 +32,7 @@ module Puma
32
32
 
33
33
  @events = options[:events] || ::Puma::Events.new
34
34
 
35
- conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
35
+ conf = ::Puma::Configuration.new(options, default_options.merge({ events: @events })) do |user_config, file_config, default_config|
36
36
  if options.delete(:Verbose)
37
37
  begin
38
38
  require 'rack/commonlogger' # Rack 1.x
@@ -72,7 +72,7 @@ module Puma
72
72
 
73
73
  log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
74
74
 
75
- launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)
75
+ launcher = ::Puma::Launcher.new(conf, log_writer: log_writer, events: @events)
76
76
 
77
77
  yield launcher if block_given?
78
78
  begin
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0.pre1
4
+ version: 7.0.1
5
5
  platform: java
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-09-05 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
+ name: nio4r
13
14
  requirement: !ruby/object:Gem::Requirement
14
15
  requirements:
15
16
  - - "~>"
16
17
  - !ruby/object:Gem::Version
17
18
  version: '2.0'
18
- name: nio4r
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,14 +138,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
138
  requirements:
139
139
  - - ">="
140
140
  - !ruby/object:Gem::Version
141
- version: '2.4'
141
+ version: '3.0'
142
142
  required_rubygems_version: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - ">="
145
145
  - !ruby/object:Gem::Version
146
146
  version: '0'
147
147
  requirements: []
148
- rubygems_version: 3.6.9
148
+ rubygems_version: 3.6.3
149
149
  specification_version: 4
150
150
  summary: A Ruby/Rack web server built for parallelism.
151
151
  test_files: []