puma 6.5.0 → 6.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +43 -2
- data/README.md +9 -1
- data/docs/fork_worker.md +7 -1
- data/docs/java_options.md +6 -0
- data/docs/plugins.md +4 -0
- data/docs/stats.md +6 -2
- data/ext/puma_http11/org/jruby/puma/Http11.java +1 -1
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/app/status.rb +1 -1
- data/lib/puma/binder.rb +7 -0
- data/lib/puma/cluster/worker.rb +9 -6
- data/lib/puma/cluster/worker_handle.rb +1 -1
- data/lib/puma/cluster.rb +12 -8
- data/lib/puma/configuration.rb +2 -0
- data/lib/puma/const.rb +10 -9
- data/lib/puma/dsl.rb +30 -10
- data/lib/puma/launcher.rb +14 -5
- data/lib/puma/runner.rb +4 -1
- data/lib/puma/sd_notify.rb +1 -4
- data/lib/puma/server.rb +9 -5
- data/lib/puma/thread_pool.rb +4 -3
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94e6b5d56525a92e2e279d59467572a254c7c03b9dc14a3e91ec5eba67b54620
|
4
|
+
data.tar.gz: 55e78ab10a5d222cce09dc89a92fbbd15d8e8ae7abbec95ca309e2903f68bd97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 750f9ec059b9710eb5ae739dc04ad600fff8386a40dc3ef83500189caacf8b7413d01eb60d751befd1aa077f3565e60617d13ceba8b9a0c29912abf410b700ff
|
7
|
+
data.tar.gz: 1a56b1696333ae86e643bd045ebe83f6a1700ac5df948113a443326e867ce17bf3f4b7e05e01cda6b99605130a2b77ccf49d2ae153ad2e879971c7238d652548
|
data/History.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
## 6.6.0 / 2025-01-29
|
2
|
+
|
3
|
+
* Features
|
4
|
+
* Option to turn off SIGUSR2 trapping ([#3570], [#3567])
|
5
|
+
* Shorten `ThreadPool` trimmer and reaper thread names ([#3383])
|
6
|
+
* Add after_refork hook ([#3386])
|
7
|
+
* Add busy threads stat ([#3517])
|
8
|
+
* Add a debug log before running each type of hook ([#3375])
|
9
|
+
* Allow alternative schemes in Binder ([#3348], [#3302])
|
10
|
+
* Avoid spawning `Threadpool#trim` thread if pool size is fixed ([#3384])
|
11
|
+
|
12
|
+
* Bugfixes
|
13
|
+
* Change `HttpParserError` to be subclass of `StandardError` ([#3590], [#3552])
|
14
|
+
* added test cases
|
15
|
+
* fix update phased restart symlink folder
|
16
|
+
|
17
|
+
* Performance
|
18
|
+
* Only ping worker 0 during phased restart if using fork worker ([#3568])
|
19
|
+
|
20
|
+
* Refactor
|
21
|
+
* Fix multi-delimiter split to get status app token ([#3505])
|
22
|
+
* Change ping to use const ([#3595])
|
23
|
+
* Fixup use of Puma::Const::PipeRequest constants ([#3565])
|
24
|
+
* Update DSL hook processing logic to be consistent ([#3376])
|
25
|
+
|
1
26
|
## 6.5.0 / 2024-11-23
|
2
27
|
|
3
28
|
* Features
|
@@ -2125,6 +2150,22 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
2125
2150
|
* Bugfixes
|
2126
2151
|
* Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
|
2127
2152
|
|
2153
|
+
[#3570]:https://github.com/puma/puma/pull/3570 "PR by @mohamedhafez, merged 2024-12-30"
|
2154
|
+
[#3567]:https://github.com/puma/puma/issues/3567 "Issue by @mohamedhafez, closed 2024-12-30"
|
2155
|
+
[#3383]:https://github.com/puma/puma/pull/3383 "PR by @joshuay03, merged 2024-11-29"
|
2156
|
+
[#3386]:https://github.com/puma/puma/pull/3386 "PR by @Drakula2k, merged 2024-11-27"
|
2157
|
+
[#3517]:https://github.com/puma/puma/pull/3517 "PR by @jjb, merged 2024-11-26"
|
2158
|
+
[#3375]:https://github.com/puma/puma/pull/3375 "PR by @joshuay03, merged 2024-11-23"
|
2159
|
+
[#3348]:https://github.com/puma/puma/pull/3348 "PR by @tomurb, merged 2024-11-23"
|
2160
|
+
[#3302]:https://github.com/puma/puma/issues/3302 "Issue by @benburkert, closed 2024-11-23"
|
2161
|
+
[#3384]:https://github.com/puma/puma/pull/3384 "PR by @joshuay03, merged 2024-11-23"
|
2162
|
+
[#3590]:https://github.com/puma/puma/pull/3590 "PR by @MSP-Greg, merged 2025-01-01"
|
2163
|
+
[#3552]:https://github.com/puma/puma/issues/3552 "Issue by @utay, closed 2025-01-01"
|
2164
|
+
[#3568]:https://github.com/puma/puma/pull/3568 "PR by @joshuay03, merged 2024-12-11"
|
2165
|
+
[#3505]:https://github.com/puma/puma/pull/3505 "PR by @AnthonyClark, merged 2025-01-27"
|
2166
|
+
[#3595]:https://github.com/puma/puma/pull/3595 "PR by @nateberkopec, merged 2025-01-07"
|
2167
|
+
[#3565]:https://github.com/puma/puma/pull/3565 "PR by @MSP-Greg, merged 2024-11-28"
|
2168
|
+
[#3376]:https://github.com/puma/puma/pull/3376 "PR by @joshuay03, merged 2024-11-23"
|
2128
2169
|
[#3407]:https://github.com/puma/puma/pull/3407 "PR by @JacobEvelyn, merged 2024-11-05"
|
2129
2170
|
[#3439]:https://github.com/puma/puma/pull/3439 "PR by @codergeek121, merged 2024-11-04"
|
2130
2171
|
[#3437]:https://github.com/puma/puma/issues/3437 "Issue by @rafaelfranca, closed 2024-11-04"
|
@@ -2709,14 +2750,14 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
2709
2750
|
[#782]:https://github.com/puma/puma/issues/782 "Issue by @Tonkpils, closed 2016-07-19"
|
2710
2751
|
[#1010]:https://github.com/puma/puma/issues/1010 "Issue by @mneumark, closed 2016-07-19"
|
2711
2752
|
[#959]:https://github.com/puma/puma/issues/959 "Issue by @mwpastore, closed 2016-04-22"
|
2712
|
-
[#840]:https://github.com/puma/puma/issues/840 "Issue by @
|
2753
|
+
[#840]:https://github.com/puma/puma/issues/840 "Issue by @marisawallace, closed 2016-04-07"
|
2713
2754
|
[#1007]:https://github.com/puma/puma/pull/1007 "PR by @willnet, merged 2016-06-24"
|
2714
2755
|
[#1014]:https://github.com/puma/puma/pull/1014 "PR by @szymon-jez, merged 2016-07-11"
|
2715
2756
|
[#1015]:https://github.com/puma/puma/pull/1015 "PR by @bf4, merged 2016-07-19"
|
2716
2757
|
[#1017]:https://github.com/puma/puma/pull/1017 "PR by @jorihardman, merged 2016-07-19"
|
2717
2758
|
[#954]:https://github.com/puma/puma/pull/954 "PR by @jf, merged 2016-04-12"
|
2718
2759
|
[#955]:https://github.com/puma/puma/pull/955 "PR by @jf, merged 2016-04-22"
|
2719
|
-
[#956]:https://github.com/puma/puma/pull/956 "PR by @
|
2760
|
+
[#956]:https://github.com/puma/puma/pull/956 "PR by @marisawallace, merged 2016-04-12"
|
2720
2761
|
[#960]:https://github.com/puma/puma/pull/960 "PR by @kmayer, merged 2016-04-15"
|
2721
2762
|
[#969]:https://github.com/puma/puma/pull/969 "PR by @frankwong15, merged 2016-05-10"
|
2722
2763
|
[#970]:https://github.com/puma/puma/pull/970 "PR by @willnet, merged 2016-04-26"
|
data/README.md
CHANGED
@@ -159,7 +159,7 @@ on_worker_boot do
|
|
159
159
|
end
|
160
160
|
```
|
161
161
|
|
162
|
-
In addition, there is an `on_refork`
|
162
|
+
In addition, there is an `on_refork` and `after_refork` hooks which are used only in [`fork_worker` mode](docs/fork_worker.md),
|
163
163
|
when the worker 0 child process forks a grandchild worker:
|
164
164
|
|
165
165
|
```ruby
|
@@ -169,6 +169,13 @@ on_refork do
|
|
169
169
|
end
|
170
170
|
```
|
171
171
|
|
172
|
+
```ruby
|
173
|
+
after_refork do
|
174
|
+
# Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
|
175
|
+
# child process after it forks a grandchild worker.
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
172
179
|
Importantly, note the following considerations when Ruby forks a child process:
|
173
180
|
|
174
181
|
1. File descriptors such as network sockets **are** copied from the parent to the forked
|
@@ -186,6 +193,7 @@ Therefore, we recommend the following:
|
|
186
193
|
2. If (1) is not possible, use `before_fork` and `on_refork` to disconnect the parent's socket
|
187
194
|
connections when forking, so that they are not accidentally copied to the child process.
|
188
195
|
3. Use `on_worker_boot` to restart any background threads on the forked child.
|
196
|
+
4. Use `after_refork` to restart any background threads on the parent.
|
189
197
|
|
190
198
|
#### Master process lifecycle hooks
|
191
199
|
|
data/docs/fork_worker.md
CHANGED
@@ -24,7 +24,13 @@ The `fork_worker` option allows your application to be initialized only once for
|
|
24
24
|
|
25
25
|
### Usage Considerations
|
26
26
|
|
27
|
-
- `fork_worker` introduces
|
27
|
+
- `fork_worker` introduces new `on_refork` and `after_refork` configuration hooks. Note the following:
|
28
|
+
- When initially forking the parent process to the worker 0 child, `before_fork` will trigger on the parent process and `on_worker_boot` will trigger on the worker 0 child as normal.
|
29
|
+
- When forking the worker 0 child to grandchild workers, `on_refork` and `after_refork` will trigger on the worker 0 child, and `on_worker_boot` will trigger on each grandchild worker.
|
30
|
+
- For clarity, `before_fork` does not trigger on worker 0, and `after_refork` does not trigger on the grandchild.
|
31
|
+
- As a general migration guide:
|
32
|
+
- Copy any logic within your existing `before_fork` hook to the `on_refork` hook.
|
33
|
+
- Consider to copy logic from your `on_worker_boot` hook to the `after_refork` hook, if it is needed to reset the state of worker 0 after it forks.
|
28
34
|
|
29
35
|
### Limitations
|
30
36
|
|
data/docs/java_options.md
CHANGED
@@ -12,6 +12,7 @@ Moreover, default values may be used in case of invalid inputs.
|
|
12
12
|
| PUMA_QUERY_STRING_MAX_LENGTH | 1024 * 10 | Positive natural number |
|
13
13
|
| PUMA_REQUEST_PATH_MAX_LENGTH | 8192 | Positive natural number |
|
14
14
|
| PUMA_REQUEST_URI_MAX_LENGTH | 1024 * 12 | Positive natural number |
|
15
|
+
| PUMA_SKIP_SIGUSR2 | nil | n/a |
|
15
16
|
|
16
17
|
## Examples
|
17
18
|
|
@@ -46,3 +47,8 @@ foo@bar:~ curl "http://localhost:9292${path}"
|
|
46
47
|
Hello World
|
47
48
|
```
|
48
49
|
|
50
|
+
### Java Flight Recorder Compatibility
|
51
|
+
|
52
|
+
Unfortunately Java Flight Recorder uses `SIGUSR2` internally. If you wish to
|
53
|
+
use JFR, turn off Puma's trapping of `SIGUSR2` by setting the environment variable
|
54
|
+
`PUMA_SKIP_SIGUSR2` to any value.
|
data/docs/plugins.md
CHANGED
@@ -36,3 +36,7 @@ object that is useful for additional configuration.
|
|
36
36
|
|
37
37
|
Public methods in [`Puma::Plugin`](../lib/puma/plugin.rb) are treated as a
|
38
38
|
public API for plugins.
|
39
|
+
|
40
|
+
## Binder hooks
|
41
|
+
|
42
|
+
There's `Puma::Binder#before_parse` method that allows to add proc to run before the body of `Puma::Binder#parse`. Example of usage can be found in [that repository](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/plugin.rb#L97-L118) (`before_parse_hook` could be renamed `before_parse`, making monkey patching of [binder.rb](https://github.com/anchordotdev/puma-acme/blob/v0.1.3/lib/puma/acme/binder.rb) is unnecessary).
|
data/docs/stats.md
CHANGED
@@ -55,10 +55,14 @@ end
|
|
55
55
|
|
56
56
|
When Puma runs in single mode, these stats are available at the top level. When Puma runs in cluster mode, these stats are available within the `worker_status` array in a hash labeled `last_status`, in an array of hashes where one hash represents each worker.
|
57
57
|
|
58
|
-
* backlog: requests that are waiting for an available thread to be available. if this is above 0, you need more capacity
|
58
|
+
* backlog: requests that are waiting for an available thread to be available. if this is frequently above 0, you need more capacity.
|
59
59
|
* running: how many threads are spawned. A spawned thread may be busy processing a request or waiting for a new request. If `min_threads` and `max_threads` are set to the same number,
|
60
60
|
this will be a never-changing number (other than rare cases when a thread dies, etc).
|
61
|
-
*
|
61
|
+
* busy_threads: `running` - `how many threads are waiting to receive work` + `how many requests are waiting for a thread to pick them up`.
|
62
|
+
this is a "wholistic" stat reflecting the overall current state of work to be done and the capacity to do it.
|
63
|
+
* pool_capacity: `how many threads are waiting to receive work` + `max_threads` - `running`. In a typical configuration where `min_threads`
|
64
|
+
and `max_threads` are configured to the same number, this is simply `how many threads are waiting to receive work`. This number exists only as a stat
|
65
|
+
and is not used for any internal decisions, unlike `busy_theads`, which is usually a more useful stat.
|
62
66
|
* max_threads: the maximum number of threads Puma is configured to spool per worker
|
63
67
|
* requests_count: the number of requests this worker has served since starting
|
64
68
|
|
@@ -77,7 +77,7 @@ public class Http11 extends RubyObject {
|
|
77
77
|
|
78
78
|
public static void createHttp11(Ruby runtime) {
|
79
79
|
RubyModule mPuma = runtime.defineModule("Puma");
|
80
|
-
mPuma.defineClassUnder("HttpParserError",runtime.getClass("
|
80
|
+
mPuma.defineClassUnder("HttpParserError",runtime.getClass("StandardError"),runtime.getClass("StandardError").getAllocator());
|
81
81
|
|
82
82
|
RubyClass cHttpParser = mPuma.defineClassUnder("HttpParser",runtime.getObject(),ALLOCATOR);
|
83
83
|
cHttpParser.defineAnnotatedMethods(Http11.class);
|
@@ -475,7 +475,7 @@ void Init_puma_http11(void)
|
|
475
475
|
DEF_GLOBAL(server_protocol, "SERVER_PROTOCOL");
|
476
476
|
DEF_GLOBAL(request_path, "REQUEST_PATH");
|
477
477
|
|
478
|
-
eHttpParserError = rb_define_class_under(mPuma, "HttpParserError",
|
478
|
+
eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eStandardError);
|
479
479
|
rb_global_variable(&eHttpParserError);
|
480
480
|
|
481
481
|
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
|
data/lib/puma/app/status.rb
CHANGED
@@ -80,7 +80,7 @@ module Puma
|
|
80
80
|
|
81
81
|
def authenticate(env)
|
82
82
|
return true unless @auth_token
|
83
|
-
env['QUERY_STRING'].to_s.split(
|
83
|
+
env['QUERY_STRING'].to_s.split(/[&;]/).include? "token=#{@auth_token}"
|
84
84
|
end
|
85
85
|
|
86
86
|
def rack_response(status, body, content_type='application/json')
|
data/lib/puma/binder.rb
CHANGED
@@ -142,7 +142,14 @@ module Puma
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
+
def before_parse(&block)
|
146
|
+
@before_parse ||= []
|
147
|
+
@before_parse << block if block
|
148
|
+
@before_parse
|
149
|
+
end
|
150
|
+
|
145
151
|
def parse(binds, log_writer = nil, log_msg = 'Listening')
|
152
|
+
before_parse.each(&:call)
|
146
153
|
log_writer ||= @log_writer
|
147
154
|
binds.each do |str|
|
148
155
|
uri = URI.parse str
|
data/lib/puma/cluster/worker.rb
CHANGED
@@ -88,25 +88,27 @@ module Puma
|
|
88
88
|
server.begin_restart(true)
|
89
89
|
@config.run_hooks(:before_refork, nil, @log_writer, @hook_data)
|
90
90
|
end
|
91
|
+
elsif idx == -2 # refork cycle is done
|
92
|
+
@config.run_hooks(:after_refork, nil, @log_writer, @hook_data)
|
91
93
|
elsif idx == 0 # restart server
|
92
94
|
restart_server << true << false
|
93
95
|
else # fork worker
|
94
96
|
worker_pids << pid = spawn_worker(idx)
|
95
|
-
@worker_write << "#{
|
97
|
+
@worker_write << "#{PIPE_FORK}#{pid}:#{idx}\n" rescue nil
|
96
98
|
end
|
97
99
|
end
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
101
103
|
Signal.trap "SIGTERM" do
|
102
|
-
@worker_write << "#{
|
104
|
+
@worker_write << "#{PIPE_EXTERNAL_TERM}#{Process.pid}\n" rescue nil
|
103
105
|
restart_server.clear
|
104
106
|
server.stop
|
105
107
|
restart_server << false
|
106
108
|
end
|
107
109
|
|
108
110
|
begin
|
109
|
-
@worker_write << "#{
|
111
|
+
@worker_write << "#{PIPE_BOOT}#{Process.pid}:#{index}\n"
|
110
112
|
rescue SystemCallError, IOError
|
111
113
|
Puma::Util.purge_interrupt_queue
|
112
114
|
STDERR.puts "Master seems to have exited, exiting."
|
@@ -122,7 +124,7 @@ module Puma
|
|
122
124
|
|
123
125
|
stat_thread ||= Thread.new(@worker_write) do |io|
|
124
126
|
Puma.set_thread_name "stat pld"
|
125
|
-
base_payload = "
|
127
|
+
base_payload = "#{PIPE_PING}#{Process.pid}"
|
126
128
|
|
127
129
|
while true
|
128
130
|
begin
|
@@ -131,7 +133,8 @@ module Puma
|
|
131
133
|
t = server.pool_capacity || 0
|
132
134
|
m = server.max_threads || 0
|
133
135
|
rc = server.requests_count || 0
|
134
|
-
|
136
|
+
bt = server.busy_threads || 0
|
137
|
+
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads":#{m}, "requests_count":#{rc}, "busy_threads":#{bt} }\n!
|
135
138
|
io << payload
|
136
139
|
rescue IOError
|
137
140
|
Puma::Util.purge_interrupt_queue
|
@@ -147,7 +150,7 @@ module Puma
|
|
147
150
|
# exiting until any background operations are completed
|
148
151
|
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
|
149
152
|
ensure
|
150
|
-
@worker_write << "#{
|
153
|
+
@worker_write << "#{PIPE_TERM}#{Process.pid}\n" rescue nil
|
151
154
|
@worker_write.close
|
152
155
|
end
|
153
156
|
|
@@ -51,7 +51,7 @@ module Puma
|
|
51
51
|
@term
|
52
52
|
end
|
53
53
|
|
54
|
-
STATUS_PATTERN = /{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads":(?<max_threads>\d*), "requests_count":(?<requests_count>\d*) }/
|
54
|
+
STATUS_PATTERN = /{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads":(?<max_threads>\d*), "requests_count":(?<requests_count>\d*), "busy_threads":(?<busy_threads>\d*) }/
|
55
55
|
private_constant :STATUS_PATTERN
|
56
56
|
|
57
57
|
def ping!(status)
|
data/lib/puma/cluster.rb
CHANGED
@@ -87,6 +87,10 @@ module Puma
|
|
87
87
|
|
88
88
|
if @options[:fork_worker] && all_workers_in_phase?
|
89
89
|
@fork_writer << "0\n"
|
90
|
+
|
91
|
+
if worker_at(0).phase > 0
|
92
|
+
@fork_writer << "-2\n"
|
93
|
+
end
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
@@ -456,7 +460,7 @@ module Puma
|
|
456
460
|
req = read.read_nonblock(1)
|
457
461
|
next unless req
|
458
462
|
|
459
|
-
if req ==
|
463
|
+
if req == PIPE_WAKEUP
|
460
464
|
@next_check = Time.now
|
461
465
|
next
|
462
466
|
end
|
@@ -464,7 +468,7 @@ module Puma
|
|
464
468
|
result = read.gets
|
465
469
|
pid = result.to_i
|
466
470
|
|
467
|
-
if req ==
|
471
|
+
if req == PIPE_BOOT || req == PIPE_FORK
|
468
472
|
pid, idx = result.split(':').map(&:to_i)
|
469
473
|
w = worker_at idx
|
470
474
|
w.pid = pid if w.pid.nil?
|
@@ -472,22 +476,22 @@ module Puma
|
|
472
476
|
|
473
477
|
if w = @workers.find { |x| x.pid == pid }
|
474
478
|
case req
|
475
|
-
when
|
479
|
+
when PIPE_BOOT
|
476
480
|
w.boot!
|
477
481
|
log "- Worker #{w.index} (PID: #{pid}) booted in #{w.uptime.round(2)}s, phase: #{w.phase}"
|
478
482
|
@next_check = Time.now
|
479
483
|
workers_not_booted -= 1
|
480
|
-
when
|
484
|
+
when PIPE_EXTERNAL_TERM
|
481
485
|
# external term, see worker method, Signal.trap "SIGTERM"
|
482
486
|
w.term!
|
483
|
-
when
|
487
|
+
when PIPE_TERM
|
484
488
|
w.term unless w.term?
|
485
|
-
when
|
489
|
+
when PIPE_PING
|
486
490
|
status = result.sub(/^\d+/,'').chomp
|
487
491
|
w.ping!(status)
|
488
492
|
@events.fire(:ping!, w)
|
489
493
|
|
490
|
-
if in_phased_restart && workers_not_booted.positive? && w0 = worker_at(0)
|
494
|
+
if in_phased_restart && @options[:fork_worker] && workers_not_booted.positive? && w0 = worker_at(0)
|
491
495
|
w0.ping!(status)
|
492
496
|
@events.fire(:ping!, w0)
|
493
497
|
end
|
@@ -497,7 +501,7 @@ module Puma
|
|
497
501
|
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
498
502
|
booted = true
|
499
503
|
end
|
500
|
-
when
|
504
|
+
when PIPE_IDLE
|
501
505
|
if idle_workers[pid]
|
502
506
|
idle_workers.delete pid
|
503
507
|
else
|
data/lib/puma/configuration.rb
CHANGED
data/lib/puma/const.rb
CHANGED
@@ -100,8 +100,8 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "6.
|
104
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "6.6.0"
|
104
|
+
CODE_NAME = "Return to Forever"
|
105
105
|
|
106
106
|
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
107
107
|
|
@@ -294,14 +294,15 @@ module Puma
|
|
294
294
|
|
295
295
|
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
296
296
|
|
297
|
+
# All constants are prefixed with `PIPE_` to avoid name collisions.
|
297
298
|
module PipeRequest
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
299
|
+
PIPE_WAKEUP = "!"
|
300
|
+
PIPE_BOOT = "b"
|
301
|
+
PIPE_FORK = "f"
|
302
|
+
PIPE_EXTERNAL_TERM = "e"
|
303
|
+
PIPE_TERM = "t"
|
304
|
+
PIPE_PING = "p"
|
305
|
+
PIPE_IDLE = "i"
|
305
306
|
end
|
306
307
|
end
|
307
308
|
end
|
data/lib/puma/dsl.rb
CHANGED
@@ -47,6 +47,7 @@ module Puma
|
|
47
47
|
# | on_worker_boot | :before_worker_boot | inside, before |
|
48
48
|
# | on_worker_shutdown | :before_worker_shutdown | inside, after |
|
49
49
|
# | on_refork | :before_refork | inside |
|
50
|
+
# | after_refork | :after_refork | inside |
|
50
51
|
#
|
51
52
|
class DSL
|
52
53
|
ON_WORKER_KEY = [String, Symbol].freeze
|
@@ -438,8 +439,7 @@ module Puma
|
|
438
439
|
# end
|
439
440
|
#
|
440
441
|
def on_restart(&block)
|
441
|
-
|
442
|
-
@options[:on_restart] << block
|
442
|
+
process_hook :on_restart, nil, block, 'on_restart'
|
443
443
|
end
|
444
444
|
|
445
445
|
# Command to use to restart Puma. This should be just how to
|
@@ -731,8 +731,7 @@ module Puma
|
|
731
731
|
def before_fork(&block)
|
732
732
|
warn_if_in_single_mode('before_fork')
|
733
733
|
|
734
|
-
|
735
|
-
@options[:before_fork] << block
|
734
|
+
process_hook :before_fork, nil, block, 'before_fork'
|
736
735
|
end
|
737
736
|
|
738
737
|
# Code to run in a worker when it boots to setup
|
@@ -855,9 +854,32 @@ module Puma
|
|
855
854
|
# @version 5.0.0
|
856
855
|
#
|
857
856
|
def on_refork(key = nil, &block)
|
857
|
+
warn_if_in_single_mode('on_refork')
|
858
|
+
|
858
859
|
process_hook :before_refork, key, block, 'on_refork'
|
859
860
|
end
|
860
861
|
|
862
|
+
# When `fork_worker` is enabled, code to run in Worker 0
|
863
|
+
# after all other workers are re-forked from this process,
|
864
|
+
# after the server has temporarily stopped serving requests
|
865
|
+
# (once per complete refork cycle).
|
866
|
+
#
|
867
|
+
# This can be used to re-open any connections to remote servers
|
868
|
+
# (database, Redis, ...) that were closed via on_refork.
|
869
|
+
#
|
870
|
+
# This can be called multiple times to add several hooks.
|
871
|
+
#
|
872
|
+
# @note Cluster mode with `fork_worker` enabled only.
|
873
|
+
#
|
874
|
+
# @example
|
875
|
+
# after_refork do
|
876
|
+
# puts 'After refork...'
|
877
|
+
# end
|
878
|
+
#
|
879
|
+
def after_refork(key = nil, &block)
|
880
|
+
process_hook :after_refork, key, block, 'after_refork'
|
881
|
+
end
|
882
|
+
|
861
883
|
# Provide a block to be executed just before a thread is added to the thread
|
862
884
|
# pool. Be careful: while the block executes, thread creation is delayed, and
|
863
885
|
# probably a request will have to wait too! The new thread will not be added to
|
@@ -876,8 +898,7 @@ module Puma
|
|
876
898
|
# end
|
877
899
|
#
|
878
900
|
def on_thread_start(&block)
|
879
|
-
|
880
|
-
@options[:before_thread_start] << block
|
901
|
+
process_hook :before_thread_start, nil, block, 'on_thread_start'
|
881
902
|
end
|
882
903
|
|
883
904
|
# Provide a block to be executed after a thread is trimmed from the thread
|
@@ -901,8 +922,7 @@ module Puma
|
|
901
922
|
# end
|
902
923
|
#
|
903
924
|
def on_thread_exit(&block)
|
904
|
-
|
905
|
-
@options[:before_thread_exit] << block
|
925
|
+
process_hook :before_thread_exit, nil, block, 'on_thread_exit'
|
906
926
|
end
|
907
927
|
|
908
928
|
# Code to run out-of-band when the worker is idle.
|
@@ -1415,8 +1435,8 @@ module Puma
|
|
1415
1435
|
if workers_val == 0
|
1416
1436
|
log_string =
|
1417
1437
|
"Warning: You specified code to run in a `#{hook_name}` block, " \
|
1418
|
-
"but Puma is not configured to run in cluster mode (worker count > 0
|
1419
|
-
"so your `#{hook_name}` block
|
1438
|
+
"but Puma is not configured to run in cluster mode (worker count > 0), " \
|
1439
|
+
"so your `#{hook_name}` block will not run."
|
1420
1440
|
|
1421
1441
|
LogWriter.stdio.log(log_string)
|
1422
1442
|
end
|
data/lib/puma/launcher.rb
CHANGED
@@ -167,6 +167,13 @@ module Puma
|
|
167
167
|
log "* phased-restart called but not available, restarting normally."
|
168
168
|
return restart
|
169
169
|
end
|
170
|
+
|
171
|
+
if @options.file_options[:tag].nil?
|
172
|
+
dir = File.realdirpath(@restart_dir)
|
173
|
+
@options[:tag] = File.basename(dir)
|
174
|
+
set_process_title
|
175
|
+
end
|
176
|
+
|
170
177
|
true
|
171
178
|
end
|
172
179
|
|
@@ -412,12 +419,14 @@ module Puma
|
|
412
419
|
end
|
413
420
|
|
414
421
|
def setup_signals
|
415
|
-
|
416
|
-
|
417
|
-
|
422
|
+
unless ENV["PUMA_SKIP_SIGUSR2"]
|
423
|
+
begin
|
424
|
+
Signal.trap "SIGUSR2" do
|
425
|
+
restart
|
426
|
+
end
|
427
|
+
rescue Exception
|
428
|
+
log "*** SIGUSR2 not implemented, signal based restart unavailable!"
|
418
429
|
end
|
419
|
-
rescue Exception
|
420
|
-
log "*** SIGUSR2 not implemented, signal based restart unavailable!"
|
421
430
|
end
|
422
431
|
|
423
432
|
unless Puma.jruby?
|
data/lib/puma/runner.rb
CHANGED
@@ -8,6 +8,9 @@ module Puma
|
|
8
8
|
# serve requests. This class spawns a new instance of `Puma::Server` via
|
9
9
|
# a call to `start_server`.
|
10
10
|
class Runner
|
11
|
+
|
12
|
+
include ::Puma::Const::PipeRequest
|
13
|
+
|
11
14
|
def initialize(launcher)
|
12
15
|
@launcher = launcher
|
13
16
|
@log_writer = launcher.log_writer
|
@@ -27,7 +30,7 @@ module Puma
|
|
27
30
|
def wakeup!
|
28
31
|
return unless @wakeup
|
29
32
|
|
30
|
-
@wakeup.write
|
33
|
+
@wakeup.write PIPE_WAKEUP unless @wakeup.closed?
|
31
34
|
|
32
35
|
rescue SystemCallError, IOError
|
33
36
|
Puma::Util.purge_interrupt_queue
|
data/lib/puma/sd_notify.rb
CHANGED
@@ -137,10 +137,7 @@ module Puma
|
|
137
137
|
ENV.delete("NOTIFY_SOCKET") if unset_env
|
138
138
|
|
139
139
|
begin
|
140
|
-
Addrinfo.unix(sock, :DGRAM).connect
|
141
|
-
s.close_on_exec = true
|
142
|
-
s.write(state)
|
143
|
-
end
|
140
|
+
Addrinfo.unix(sock, :DGRAM).connect { |s| s.write state }
|
144
141
|
rescue StandardError => e
|
145
142
|
raise NotifyError, "#{e.class}: #{e.message}", e.backtrace
|
146
143
|
end
|
data/lib/puma/server.rb
CHANGED
@@ -233,6 +233,11 @@ module Puma
|
|
233
233
|
@thread_pool&.pool_capacity
|
234
234
|
end
|
235
235
|
|
236
|
+
# @!attribute [r] busy_threads
|
237
|
+
def busy_threads
|
238
|
+
@thread_pool&.busy_threads
|
239
|
+
end
|
240
|
+
|
236
241
|
# Runs the server.
|
237
242
|
#
|
238
243
|
# If +background+ is true (the default) then a thread is spun
|
@@ -253,9 +258,8 @@ module Puma
|
|
253
258
|
@reactor.run
|
254
259
|
end
|
255
260
|
|
256
|
-
|
257
261
|
@thread_pool.auto_reap! if options[:reaping_time]
|
258
|
-
@thread_pool.auto_trim! if options[:auto_trim_time]
|
262
|
+
@thread_pool.auto_trim! if @min_threads != @max_threads && options[:auto_trim_time]
|
259
263
|
|
260
264
|
@check, @notify = Puma::Util.pipe unless @notify
|
261
265
|
|
@@ -340,7 +344,7 @@ module Puma
|
|
340
344
|
@idle_timeout_reached = true
|
341
345
|
|
342
346
|
if @clustered
|
343
|
-
@worker_write << "#{PipeRequest::
|
347
|
+
@worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil
|
344
348
|
next
|
345
349
|
else
|
346
350
|
@log_writer.log "- Idle timeout reached"
|
@@ -353,7 +357,7 @@ module Puma
|
|
353
357
|
|
354
358
|
if @idle_timeout_reached && @clustered
|
355
359
|
@idle_timeout_reached = false
|
356
|
-
@worker_write << "#{PipeRequest::
|
360
|
+
@worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil
|
357
361
|
end
|
358
362
|
|
359
363
|
ios.first.each do |sock|
|
@@ -646,7 +650,7 @@ module Puma
|
|
646
650
|
|
647
651
|
# List of methods invoked by #stats.
|
648
652
|
# @version 5.0.0
|
649
|
-
STAT_METHODS = [:backlog, :running, :pool_capacity, :max_threads, :requests_count].freeze
|
653
|
+
STAT_METHODS = [:backlog, :running, :pool_capacity, :max_threads, :requests_count, :busy_threads].freeze
|
650
654
|
|
651
655
|
# Returns a hash of stats about the running server for reporting purposes.
|
652
656
|
# @version 5.0.0
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -91,7 +91,8 @@ module Puma
|
|
91
91
|
with_mutex do
|
92
92
|
{ backlog: @todo.size,
|
93
93
|
running: @spawned,
|
94
|
-
pool_capacity: @waiting + (@max - @spawned)
|
94
|
+
pool_capacity: @waiting + (@max - @spawned),
|
95
|
+
busy_threads: @spawned - @waiting + @todo.size
|
95
96
|
}
|
96
97
|
end
|
97
98
|
end
|
@@ -369,12 +370,12 @@ module Puma
|
|
369
370
|
end
|
370
371
|
|
371
372
|
def auto_trim!(timeout=@auto_trim_time)
|
372
|
-
@auto_trim = Automaton.new(self, timeout, "#{@name}
|
373
|
+
@auto_trim = Automaton.new(self, timeout, "#{@name} tp trim", :trim)
|
373
374
|
@auto_trim.start!
|
374
375
|
end
|
375
376
|
|
376
377
|
def auto_reap!(timeout=@reaping_time)
|
377
|
-
@reaper = Automaton.new(self, timeout, "#{@name}
|
378
|
+
@reaper = Automaton.new(self, timeout, "#{@name} tp reap", :reap)
|
378
379
|
@reaper.start!
|
379
380
|
end
|
380
381
|
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-28 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: nio4r
|
@@ -132,7 +131,6 @@ metadata:
|
|
132
131
|
homepage_uri: https://puma.io
|
133
132
|
source_code_uri: https://github.com/puma/puma
|
134
133
|
rubygems_mfa_required: 'true'
|
135
|
-
post_install_message:
|
136
134
|
rdoc_options: []
|
137
135
|
require_paths:
|
138
136
|
- lib
|
@@ -147,8 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
145
|
- !ruby/object:Gem::Version
|
148
146
|
version: '0'
|
149
147
|
requirements: []
|
150
|
-
rubygems_version: 3.
|
151
|
-
signing_key:
|
148
|
+
rubygems_version: 3.6.3
|
152
149
|
specification_version: 4
|
153
150
|
summary: A Ruby/Rack web server built for parallelism.
|
154
151
|
test_files: []
|