puma 6.6.0 → 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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +309 -5
  3. data/README.md +41 -42
  4. data/docs/5.0-Upgrade.md +98 -0
  5. data/docs/6.0-Upgrade.md +56 -0
  6. data/docs/7.0-Upgrade.md +52 -0
  7. data/docs/8.0-Upgrade.md +100 -0
  8. data/docs/deployment.md +58 -23
  9. data/docs/fork_worker.md +5 -5
  10. data/docs/grpc.md +62 -0
  11. data/docs/images/favicon.svg +1 -0
  12. data/docs/images/running-puma.svg +1 -0
  13. data/docs/images/standard-logo.svg +1 -0
  14. data/docs/jungle/README.md +1 -1
  15. data/docs/kubernetes.md +11 -16
  16. data/docs/plugins.md +2 -2
  17. data/docs/restart.md +2 -2
  18. data/docs/signals.md +21 -21
  19. data/docs/stats.md +4 -3
  20. data/docs/systemd.md +4 -4
  21. data/ext/puma_http11/extconf.rb +2 -17
  22. data/ext/puma_http11/http11_parser.java.rl +51 -65
  23. data/ext/puma_http11/mini_ssl.c +18 -8
  24. data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
  25. data/ext/puma_http11/org/jruby/puma/Http11.java +174 -102
  26. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
  27. data/ext/puma_http11/puma_http11.c +122 -118
  28. data/lib/puma/app/status.rb +10 -2
  29. data/lib/puma/binder.rb +12 -10
  30. data/lib/puma/cli.rb +4 -6
  31. data/lib/puma/client.rb +205 -131
  32. data/lib/puma/client_env.rb +171 -0
  33. data/lib/puma/cluster/worker.rb +17 -17
  34. data/lib/puma/cluster/worker_handle.rb +38 -7
  35. data/lib/puma/cluster.rb +44 -30
  36. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  37. data/lib/puma/commonlogger.rb +3 -3
  38. data/lib/puma/configuration.rb +173 -58
  39. data/lib/puma/const.rb +11 -11
  40. data/lib/puma/control_cli.rb +7 -3
  41. data/lib/puma/detect.rb +13 -0
  42. data/lib/puma/dsl.rb +225 -108
  43. data/lib/puma/error_logger.rb +3 -1
  44. data/lib/puma/events.rb +25 -10
  45. data/lib/puma/io_buffer.rb +8 -4
  46. data/lib/puma/launcher/bundle_pruner.rb +3 -5
  47. data/lib/puma/launcher.rb +57 -53
  48. data/lib/puma/log_writer.rb +8 -2
  49. data/lib/puma/minissl.rb +0 -1
  50. data/lib/puma/plugin/systemd.rb +3 -3
  51. data/lib/puma/rack/urlmap.rb +1 -1
  52. data/lib/puma/reactor.rb +19 -13
  53. data/lib/puma/{request.rb → response.rb} +56 -212
  54. data/lib/puma/runner.rb +9 -18
  55. data/lib/puma/server.rb +182 -97
  56. data/lib/puma/server_plugin_control.rb +32 -0
  57. data/lib/puma/single.rb +7 -4
  58. data/lib/puma/state_file.rb +3 -2
  59. data/lib/puma/thread_pool.rb +170 -99
  60. data/lib/puma/util.rb +0 -7
  61. data/lib/puma.rb +10 -0
  62. data/lib/rack/handler/puma.rb +3 -3
  63. data/tools/Dockerfile +15 -5
  64. metadata +19 -7
  65. data/ext/puma_http11/ext_help.h +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94e6b5d56525a92e2e279d59467572a254c7c03b9dc14a3e91ec5eba67b54620
4
- data.tar.gz: 55e78ab10a5d222cce09dc89a92fbbd15d8e8ae7abbec95ca309e2903f68bd97
3
+ metadata.gz: 6c96b9615e3021ca787fdb02a91af1bcfc2c2201465efd375e94c0100d089ece
4
+ data.tar.gz: 620a8240509ff2acbac19e20b4d8f55aa7cef0b6fb8bef0836f31c848b9def67
5
5
  SHA512:
6
- metadata.gz: 750f9ec059b9710eb5ae739dc04ad600fff8386a40dc3ef83500189caacf8b7413d01eb60d751befd1aa077f3565e60617d13ceba8b9a0c29912abf410b700ff
7
- data.tar.gz: 1a56b1696333ae86e643bd045ebe83f6a1700ac5df948113a443326e867ce17bf3f4b7e05e01cda6b99605130a2b77ccf49d2ae153ad2e879971c7238d652548
6
+ metadata.gz: 88e2c0146d21143793a559dbb515ce22866266a5750acd0e55c9d84bbc41c536341e3602b34d4e192dad265102bc6bd93b0e300d1ee60806482aa9ba67e59e29
7
+ data.tar.gz: 6f5d132d87d2b78a3b240eec1029f7eab30ce22f5de1dfcbc1ba0bc2d253655b58594bd1104def34cb169a56aef4642666267dcadb347f2381e63179dddf1946
data/History.md CHANGED
@@ -1,3 +1,194 @@
1
+ ## 8.0.2 / 2026-05-27
2
+
3
+ * Bugfixes
4
+ * Anchor PROXY protocol v1 regex to string start and enforce max line length to prevent injection via crafted request bodies ([#3944])
5
+ * Parse PROXY protocol header only on the first request per connection to prevent spoofing on keep-alive connections ([#3944])
6
+
7
+ ## 8.0.1 / 2026-04-27
8
+
9
+ * Bugfixes
10
+ * Fix `prune_bundler` stripping user-configured `BUNDLE_*` env vars (e.g. `BUNDLE_WITHOUT`) on re-exec, which caused workers to crash on boot ([#3929])
11
+
12
+ * Performance
13
+ * Use blocks for debug logging to avoid creating log messages when debug is disabled ([#3920])
14
+
15
+ * Docs
16
+ * Fix incorrect hook names in gRPC docs ([#3923])
17
+ * Reword v8 upgrade guide IPv6 bullet for clarity ([#3928])
18
+
19
+ ## 8.0.0 / 2026-03-27
20
+
21
+ * Features
22
+ * Add `env["puma.mark_as_io_bound"]` API and `max_io_threads` config to allow IO-bound requests to exceed the thread pool max, enabling better handling of mixed workloads ([#3816], [#3894])
23
+ * Add `single` and `cluster` DSL hooks for mode-specific configuration ([#3621])
24
+ * Add `on_force` option to `shutdown_debug` to only dump thread backtraces on forced (non-graceful) shutdown ([#3671])
25
+ * Add API to dynamically update min and max thread counts at runtime via `update_thread_pool_min_max` and `ServerPluginControl` ([#3658])
26
+ * Use SIGPWR for thread backtrace dumps on Linux/JRuby where SIGINFO is unavailable ([#3829])
27
+
28
+ * Bugfixes
29
+ * Fix phased restart for `fork_worker` to avoid forking from stale worker 0 when it has been replaced ([#3853])
30
+
31
+ * Performance
32
+ * JRuby HTTP parser improvements: pre-allocated header keys, perfect hash lookup, reduced memory copies ([#3838])
33
+ * Cache downcased header key in `str_headers` to avoid redundant `String#downcase` calls, reducing allocations by ~50% per response ([#3874])
34
+
35
+ * Refactor
36
+ * Collect `env` processing into dedicated `client_env.rb` module ([#3582])
37
+ * Move event to default configuration ([#3872])
38
+
39
+ * Docs
40
+ * Add gRPC guide for configuring gRPC lifecycle hooks in clustered mode ([#3885])
41
+ * Add 7.0 upgrade guide, move 5.0/6.0 upgrade guides to docs directory ([#3900])
42
+ * Correct default values for `persistent_timeout` and `worker_boot_timeout` in DSL docs ([#3912])
43
+ * Add file descriptor limit warning in test helper for contributors ([#3893])
44
+
45
+ * Breaking changes
46
+ * Default production bind address changed from `0.0.0.0` to `::` (IPv6) when a non-loopback IPv6 interface is available; falls back to `0.0.0.0` if IPv6 is unavailable ([#3847])
47
+
48
+ ## 7.2.0 / 2026-01-20
49
+
50
+ * Features
51
+ * Add workers `:auto` ([#3827])
52
+ * Make it possible to restrict control server commands to stats ([#3787])
53
+
54
+ * Bugfixes
55
+ * Don't break if `WEB_CONCURRENCY` is set to a blank string ([#3837])
56
+ * Don't share server between worker 0 and descendants on refork ([#3602])
57
+ * Fix phase check race condition in `Puma::Cluster#check_workers` ([#3690])
58
+ * Fix advertising of CLI config before config files are loaded ([#3823])
59
+
60
+ * Performance
61
+ * 17% faster HTTP parsing through pre-interning env keys ([#3825])
62
+ * Implement `dsize` and `dcompact` functions for `Puma::HttpParser`, which makes Puma's C-extension GC-compactible ([#3828])
63
+
64
+ * Refactor
65
+ * Remove `NoMethodError` rescue in `Reactor#select_loop` ([#3831])
66
+ * Various cleanups in the C extension ([#3814])
67
+ * Monomorphize `handle_request` return ([#3802])
68
+
69
+ * Docs
70
+ * Change link to `docs/deployment.md` in `README.md` ([#3848])
71
+ * Fix formatting for each signal description in signals.md ([#3813])
72
+ * Update deployment and Kubernetes docs with Puma configuration tips ([#3807])
73
+ * Rename master to main ([#3809], [#3808], [#3800])
74
+ * Fix some minor typos in the docs ([#3804])
75
+ * Add `GOVERNANCE.md`, `MAINTAINERS` ([#3826])
76
+ * Remove Code Climate badge ([#3820])
77
+ * Add @joshuay03 to the maintainer list
78
+
79
+ * CI
80
+ * Use Minitest 6 where applicable ([#3859])
81
+ * Many test suite improvements and flake fixes ([#3861], [#3863], [#3860], [#3852], [#3857], [#3856], [#3845], [#3843], [#3842], [#3841], [#3822], [#3817], [#3764])
82
+
83
+ ## 7.1.0 / 2025-10-16
84
+
85
+ * Features
86
+ * Introduce `after_worker_shutdown` hook ([#3707])
87
+ * Reintroduce keepalive "fast inline" behavior. Provides faster (8x on JRuby & 1.4x on Ruby) pipeline processing ([#3794])
88
+
89
+ * Bugfixes
90
+ * Skip reading zero bytes when request body is buffered ([#3795])
91
+ * Fix `PUMA_LOG_CONFIG=1` logging twice with prune_bundler enabled ([#3778])
92
+ * Fix prune_bundler not showing in `PUMA_LOG_CONFIG=1` output ([#3779])
93
+ * Guard ThreadPool method call, which may be nil during shutdown ([#3791], [#3790])
94
+ * Set `Thread.current.puma_server` in Thread init code, not every request ([#3774])
95
+ * Fix race condition while deleting pidfile ([#3657])
96
+
97
+ ## 7.0.4 / 2025-09-23
98
+
99
+ * Bugfixes
100
+ * Fix SSL_shutdown error handling ([#3703])
101
+ * Strip whitespace from the beginnings of request header values. ([#3742])
102
+
103
+ * Performance
104
+ * puma_http11.c: Use interned UTF-8 strings for hash keys ([#3754])
105
+ * Move sleep cluster logic to its own class ([#3746], [#3740])
106
+
107
+ ## 7.0.3 / 2025-09-13
108
+
109
+ * Performance
110
+ * server.rb - process_client - add ka to todo if readable & complete ([#3748])
111
+
112
+ * Bugfixes
113
+ * Convert PUMA_PERSISTENT_TIMEOUT to an Integer ([#3749])
114
+
115
+ ## 7.0.2 / 2025-09-08
116
+
117
+ * Bugfixes
118
+ * bug: control_cli.rb - Fixup `pumactl` code to load puma.rb for `deprecate_method_change` ([#3736], [#3734])
119
+ * Replace sleep spin lock with condition variable ([#3729])
120
+ * Fix Puma not booting if queue_requests disabled ([#3731])
121
+
122
+ ## 7.0.1 / 2025-09-06
123
+
124
+ * Bugfixes
125
+ * Add backward compatibility aliases for Events class methods ([#3725])
126
+
127
+ ## 7.0.0 / 2025-09-03
128
+
129
+ * Breaking changes
130
+ * Set default `max_keep_alive` to 999 ([#3719])
131
+ * Increase `persistent_timeout` default to 65 seconds ([#3378])
132
+ * Raise an ArgumentError if no block given to hooks ([#3377])
133
+ * Don't set env['HTTP_VERSION'] for Rack > 3.1 ([#3711], [#3576])
134
+ * Runner.rb - remove `ruby_engine` method, deprecated Nov-2024 ([#3701])
135
+ * Config `preload_app!` is now the default for clustered mode ([#3297])
136
+ * Config instance must be `clamp`-d before reading any values ([#3297])
137
+ * Response headers set to lowercase ([#3704])
138
+ * Update minimum Ruby version to 3.0 ([#3698])
139
+ * Rename callback hooks ([#3438])
140
+
141
+ | Old hook name| New hook name|
142
+ |----------|----------|
143
+ | on_worker_boot | before_worker_boot |
144
+ | on_worker_shutdown | before_worker_shutdown |
145
+ | on_restart | before_restart |
146
+ | on_booted | after_booted |
147
+ | on_stopped | after_stopped |
148
+ | on_refork | before_refork |
149
+ | on_thread_start | before_thread_start |
150
+ | on_thread_exit | before_thread_exit |
151
+ | on_worker_fork | before_worker_fork |
152
+
153
+ * Features
154
+ * Fix long tail response problem with keepalive connections ([#3678]) (Previously released in 7.0.0.pre1, this was a high effort change)
155
+ * Introduce support for fiber-per-request. ([#3101])
156
+ * Add support for `rack.response_finished` ([#3681])
157
+ * Feature/support custom logger with request logs ([#3140])
158
+
159
+ * Bugfixes
160
+ * Fix error_logger inproperly logging `env[QUERY_STRING]` ([#3713], [#3625])
161
+ * Fix handling of invalid Transfer-Encoding header errors ([#3702])
162
+ * Fix socket leak on monitor wakeup `NoMethodError` in `Reactor#select_loop` ([#3696], [#3695])
163
+ * CI: puma_socket.rb fixup socket/request writes ([#3684])
164
+ * Warn when RUBY_MN_THREADS env var is set ([#3721])
165
+ * Improve the DSL `preload_app!` doc ([#3712])
166
+ * Fix the ability to focus individual tests ([#3705])
167
+ * Set env['rack.hijack'] to client.method(:full_hijack) ([#3073])
168
+
169
+ * Performance
170
+ * server.rb - initialize ivars `@reactor` and `@env_set_http_version` ([#3714])
171
+
172
+ * Refactor
173
+ * Simplify `Puma::DSL#process_hook` logic ([#3710])
174
+ * Dry up deprecation warnings and fix deprecation warnings when running CI. ([#3709], [#3708])
175
+ * Ensure and enforce that configs are loaded before options are accessed ([#3616])
176
+
177
+ ## 7.0.0.pre1 / 2025-07-31
178
+
179
+ * Changed
180
+ * Fix long tail response problem with keepalive connections ([#3678])
181
+
182
+ ## 6.6.1 / 2025-07-30
183
+
184
+ * Bugfixes
185
+ * Accept `to_path` to be `nil` on request bodies ([#3635])
186
+ * Fix single runner stats before the server start ([#3572])
187
+ * Fix incomplete worker boot state on refork ([#3601])
188
+ * Improve HttpParserError messages for better debugging ([#3586])
189
+ * Fix refork logs to distinguish from phased restarts ([#3598])
190
+ * Fix `rack.after_reply` so it doesn't interrupt chain on error ([#3680])
191
+
1
192
  ## 6.6.0 / 2025-01-29
2
193
 
3
194
  * Features
@@ -163,7 +354,7 @@
163
354
 
164
355
  * Features
165
356
  * Ability to supply a custom logger ([#2770], [#2511])
166
- * Warn when clustered-only hooks are defined in single mode ([#3089])
357
+ * Warn when cluster mode-only hooks are defined in single mode ([#3089])
167
358
  * Adds the on_booted event ([#2709])
168
359
 
169
360
  * Bugfixes
@@ -758,7 +949,7 @@ Each patchlevel release contains a separate security fix. We recommend simply up
758
949
  * Fix Java 8 support ([#1773])
759
950
  * Fix error `uninitialized constant Puma::Cluster` ([#1731])
760
951
  * Fix `not_token` being able to be set to true ([#1803])
761
- * Fix "Hang on SIGTERM with ruby 2.6 in clustered mode" (PR [#1741], [#1674], [#1720], [#1730], [#1755])
952
+ * Fix "Hang on SIGTERM with ruby 2.6 in cluster mode" (PR [#1741], [#1674], [#1720], [#1730], [#1755])
762
953
 
763
954
  ## 3.12.1 / 2019-03-19
764
955
 
@@ -1169,7 +1360,7 @@ Each patchlevel release contains a separate security fix. We recommend simply up
1169
1360
  * 4 minor features:
1170
1361
 
1171
1362
  * Listen to unix socket with provided backlog if any
1172
- * Improves the clustered stats to report worker stats
1363
+ * Improves the cluster mode stats to report worker stats
1173
1364
  * Pass the env to the lowlevel_error handler. Fixes [#854]
1174
1365
  * Treat path-like hosts as unix sockets. Fixes [#824]
1175
1366
 
@@ -1896,7 +2087,7 @@ The "clearly I don't have enough tests for the config" release.
1896
2087
 
1897
2088
  * 3 doc changes:
1898
2089
  * Add note about on_worker_boot hook
1899
- * Add some documentation for Clustered mode
2090
+ * Add some documentation for Cluster mode
1900
2091
  * Added quotes to /etc/puma.conf
1901
2092
 
1902
2093
  ## 2.0.1 / 2013-04-30
@@ -2150,6 +2341,119 @@ be added back in a future date when a java Puma::MiniSSL is added.
2150
2341
  * Bugfixes
2151
2342
  * Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
2152
2343
 
2344
+ [#3944]:https://github.com/puma/puma/pull/3944 "PR by Nate Berkopec, merged 2026-05-26"
2345
+ [#3929]:https://github.com/puma/puma/pull/3929 "PR by Joshua Young, merged 2026-04-26"
2346
+ [#3928]:https://github.com/puma/puma/pull/3928 "PR by Nate Berkopec, merged 2026-04-16"
2347
+ [#3923]:https://github.com/puma/puma/pull/3923 "PR by Joshua Young, merged 2026-04-10"
2348
+ [#3920]:https://github.com/puma/puma/pull/3920 "PR by Petrik de Heus, merged 2026-04-10"
2349
+ [#3912]:https://github.com/puma/puma/pull/3912 "PR by Bengt-Ove Hollaender, merged 2026-03-26"
2350
+ [#3900]:https://github.com/puma/puma/pull/3900 "PR by Nate Berkopec, merged 2026-03-26"
2351
+ [#3894]:https://github.com/puma/puma/pull/3894 "PR by Joshua Young, merged 2026-03-07"
2352
+ [#3893]:https://github.com/puma/puma/pull/3893 "PR by Sasha Stadnyk, merged 2026-03-22"
2353
+ [#3885]:https://github.com/puma/puma/pull/3885 "PR by Joshua Young, merged 2026-02-18"
2354
+ [#3874]:https://github.com/puma/puma/pull/3874 "PR by Hadrien Blanc, merged 2026-01-28"
2355
+ [#3872]:https://github.com/puma/puma/pull/3872 "PR by Nate Berkopec, merged 2026-01-27"
2356
+ [#3853]:https://github.com/puma/puma/pull/3853 "PR by Krzysztof Jablonski, merged 2026-03-09"
2357
+ [#3847]:https://github.com/puma/puma/pull/3847 "PR by Richard Schneeman, merged 2026-03-26"
2358
+ [#3838]:https://github.com/puma/puma/pull/3838 "PR by Charles Oliver Nutter, merged 2026-01-31"
2359
+ [#3829]:https://github.com/puma/puma/pull/3829 "PR by Nate Berkopec, merged 2026-01-27"
2360
+ [#3816]:https://github.com/puma/puma/pull/3816 "PR by Jean Boussier, merged 2026-03-07"
2361
+ [#3671]:https://github.com/puma/puma/pull/3671 "PR by Joshua Young, merged 2026-03-08"
2362
+ [#3658]:https://github.com/puma/puma/pull/3658 "PR by Yuki Nishijima, merged 2026-02-18"
2363
+ [#3621]:https://github.com/puma/puma/pull/3621 "PR by Joshua Young, merged 2026-02-22"
2364
+ [#3582]:https://github.com/puma/puma/pull/3582 "PR by MSP-Greg, merged 2026-02-22"
2365
+ [#3863]:https://github.com/puma/puma/pull/3863 "PR by Nate Berkopec, merged 2026-01-20"
2366
+ [#3861]:https://github.com/puma/puma/pull/3861 "PR by MSP-Greg, merged 2026-01-20"
2367
+ [#3860]:https://github.com/puma/puma/pull/3860 "PR by MSP-Greg, merged 2026-01-16"
2368
+ [#3859]:https://github.com/puma/puma/pull/3859 "PR by MSP-Greg, merged 2026-01-16"
2369
+ [#3857]:https://github.com/puma/puma/pull/3857 "PR by Aaron Patterson, merged 2026-01-12"
2370
+ [#3856]:https://github.com/puma/puma/pull/3856 "PR by MSP-Greg, merged 2026-01-12"
2371
+ [#3852]:https://github.com/puma/puma/pull/3852 "PR by Miłosz Bieniek, merged 2026-01-14"
2372
+ [#3848]:https://github.com/puma/puma/pull/3848 "PR by Miłosz Bieniek, merged 2025-12-27"
2373
+ [#3845]:https://github.com/puma/puma/pull/3845 "PR by MSP-Greg, merged 2025-12-19"
2374
+ [#3843]:https://github.com/puma/puma/pull/3843 "PR by MSP-Greg, merged 2025-12-18"
2375
+ [#3842]:https://github.com/puma/puma/pull/3842 "PR by MSP-Greg, merged 2025-12-18"
2376
+ [#3841]:https://github.com/puma/puma/pull/3841 "PR by MSP-Greg, merged 2025-12-18"
2377
+ [#3837]:https://github.com/puma/puma/pull/3837 "PR by John Bachir, merged 2026-01-09"
2378
+ [#3833]:https://github.com/puma/puma/pull/3833 "PR by Patrik Ragnarsson, merged 2025-11-25"
2379
+ [#3831]:https://github.com/puma/puma/pull/3831 "PR by Joshua Young, merged 2025-11-25"
2380
+ [#3828]:https://github.com/puma/puma/pull/3828 "PR by Jean Boussier, merged 2025-11-21"
2381
+ [#3827]:https://github.com/puma/puma/pull/3827 "PR by Nate Berkopec, merged 2026-01-20"
2382
+ [#3826]:https://github.com/puma/puma/pull/3826 "PR by Nate Berkopec, merged 2026-01-20"
2383
+ [#3825]:https://github.com/puma/puma/pull/3825 "PR by Jean Boussier, merged 2025-11-19"
2384
+ [#3823]:https://github.com/puma/puma/pull/3823 "PR by Joshua Young, merged 2025-11-18"
2385
+ [#3822]:https://github.com/puma/puma/pull/3822 "PR by Nate Berkopec, merged 2025-11-17"
2386
+ [#3820]:https://github.com/puma/puma/pull/3820 "PR by Nate Berkopec, merged 2025-11-19"
2387
+ [#3817]:https://github.com/puma/puma/pull/3817 "PR by Nate Berkopec, merged 2025-11-17"
2388
+ [#3814]:https://github.com/puma/puma/pull/3814 "PR by Jean Boussier, merged 2025-11-17"
2389
+ [#3813]:https://github.com/puma/puma/pull/3813 "PR by Masafumi Koba, merged 2025-11-17"
2390
+ [#3809]:https://github.com/puma/puma/pull/3809 "PR by Patrik Ragnarsson, merged 2025-10-26"
2391
+ [#3808]:https://github.com/puma/puma/pull/3808 "PR by Nymuxyzo, merged 2025-10-26"
2392
+ [#3807]:https://github.com/puma/puma/pull/3807 "PR by Nate Berkopec, merged 2025-10-28"
2393
+ [#3804]:https://github.com/puma/puma/pull/3804 "PR by Joe Rafaniello, merged 2025-10-21"
2394
+ [#3802]:https://github.com/puma/puma/pull/3802 "PR by Richard Schneeman, merged 2025-10-20"
2395
+ [#3800]:https://github.com/puma/puma/pull/3800 "PR by MSP-Greg, merged 2025-10-19"
2396
+ [#3787]:https://github.com/puma/puma/pull/3787 "PR by Stan Hu, merged 2025-10-17"
2397
+ [#3764]:https://github.com/puma/puma/pull/3764 "PR by MSP-Greg, merged 2025-10-17"
2398
+ [#3690]:https://github.com/puma/puma/pull/3690 "PR by Joshua Young, merged 2025-11-18"
2399
+ [#3602]:https://github.com/puma/puma/pull/3602 "PR by Joshua Young, merged 2025-11-28"
2400
+
2401
+ [#3707]:https://github.com/puma/puma/pull/3707 "PR by @nerdrew, merged 2025-10-02"
2402
+ [#3794]:https://github.com/puma/puma/pull/3794 "PR by @schneems, merged 2025-10-16"
2403
+ [#3795]:https://github.com/puma/puma/pull/3795 "PR by @MSP-Greg, merged 2025-10-16"
2404
+ [#3778]:https://github.com/puma/puma/pull/3778 "PR by @joshuay03, merged 2025-10-16"
2405
+ [#3779]:https://github.com/puma/puma/pull/3779 "PR by @joshuay03, merged 2025-10-16"
2406
+ [#3791]:https://github.com/puma/puma/pull/3791 "PR by @MSP-Greg, merged 2025-10-09"
2407
+ [#3790]:https://github.com/puma/puma/issues/3790 "Issue by @eric-wtfoxtrot, closed 2025-10-09"
2408
+ [#3774]:https://github.com/puma/puma/pull/3774 "PR by @MSP-Greg, merged 2025-10-16"
2409
+ [#3657]:https://github.com/puma/puma/pull/3657 "PR by @marksmith, merged 2025-10-16"
2410
+ [#3703]:https://github.com/puma/puma/pull/3703 "PR by @marshall-lee, merged 2025-09-20"
2411
+ [#3742]:https://github.com/puma/puma/pull/3742 "PR by @kenballus, merged 2025-09-18"
2412
+ [#3754]:https://github.com/puma/puma/pull/3754 "PR by @byroot, merged 2025-09-18"
2413
+ [#3746]:https://github.com/puma/puma/pull/3746 "PR by @schneems, merged 2025-09-18"
2414
+ [#3740]:https://github.com/puma/puma/issues/3740 "Issue by @joshuay03, closed 2025-09-18"
2415
+ [#3748]:https://github.com/puma/puma/pull/3748 "PR by @MSP-Greg, merged 2025-09-14"
2416
+ [#3749]:https://github.com/puma/puma/pull/3749 "PR by @schneems, merged 2025-09-14"
2417
+ [#3736]:https://github.com/puma/puma/pull/3736 "PR by @MSP-Greg, merged 2025-09-08"
2418
+ [#3734]:https://github.com/puma/puma/issues/3734 "Issue by @espen, closed 2025-09-08"
2419
+ [#3729]:https://github.com/puma/puma/pull/3729 "PR by @bensheldon, merged 2025-09-08"
2420
+ [#3731]:https://github.com/puma/puma/pull/3731 "PR by @stanhu, merged 2025-09-06"
2421
+ [#3725]:https://github.com/puma/puma/pull/3725 "PR by @tannakartikey, merged 2025-09-05"
2422
+ [#3719]:https://github.com/puma/puma/pull/3719 "PR by @schneems, merged 2025-09-03"
2423
+ [#3378]:https://github.com/puma/puma/pull/3378 "PR by @shayonj, merged 2025-08-19"
2424
+ [#3377]:https://github.com/puma/puma/pull/3377 "PR by @joshuay03, merged 2025-08-12"
2425
+ [#3711]:https://github.com/puma/puma/pull/3711 "PR by @MSP-Greg, merged 2025-08-28"
2426
+ [#3576]:https://github.com/puma/puma/issues/3576 "Issue by @pdalberti, closed 2025-08-28"
2427
+ [#3701]:https://github.com/puma/puma/pull/3701 "PR by @MSP-Greg, merged 2025-08-26"
2428
+ [#3297]:https://github.com/puma/puma/pull/3297 "PR by @joshuay03, merged 2025-08-26"
2429
+ [#3704]:https://github.com/puma/puma/pull/3704 "PR by @schneems, merged 2025-08-25"
2430
+ [#3698]:https://github.com/puma/puma/pull/3698 "PR by @schneems, merged 2025-08-21"
2431
+ [#3438]:https://github.com/puma/puma/pull/3438 "PR by @tannakartikey, merged 2025-08-25"
2432
+ [#3678]:https://github.com/puma/puma/pull/3678 "PR by @MSP-Greg, merged 2025-07-31"
2433
+ [#3101]:https://github.com/puma/puma/pull/3101 "PR by @ioquatix, merged 2025-08-25"
2434
+ [#3681]:https://github.com/puma/puma/pull/3681 "PR by @byroot, merged 2025-08-15"
2435
+ [#3140]:https://github.com/puma/puma/pull/3140 "PR by @phyzical, merged 2025-08-12"
2436
+ [#3713]:https://github.com/puma/puma/pull/3713 "PR by @MSP-Greg, merged 2025-08-29"
2437
+ [#3625]:https://github.com/puma/puma/pull/3625 "PR by @bhooshiek-narendiran, closed 2025-08-29"
2438
+ [#3702]:https://github.com/puma/puma/pull/3702 "PR by @marshall-lee, merged 2025-08-25"
2439
+ [#3696]:https://github.com/puma/puma/pull/3696 "PR by @joshuay03, merged 2025-08-22"
2440
+ [#3695]:https://github.com/puma/puma/issues/3695 "Issue by @joshuay03, closed 2025-08-22"
2441
+ [#3684]:https://github.com/puma/puma/pull/3684 "PR by @MSP-Greg, merged 2025-08-02"
2442
+ [#3721]:https://github.com/puma/puma/pull/3721 "PR by @schneems, merged 2025-09-03"
2443
+ [#3712]:https://github.com/puma/puma/pull/3712 "PR by @joshuay03, merged 2025-08-28"
2444
+ [#3705]:https://github.com/puma/puma/pull/3705 "PR by @schneems, merged 2025-08-25"
2445
+ [#3073]:https://github.com/puma/puma/pull/3073 "PR by @MSP-Greg, merged 2025-08-12"
2446
+ [#3714]:https://github.com/puma/puma/pull/3714 "PR by @MSP-Greg, merged 2025-08-29"
2447
+ [#3710]:https://github.com/puma/puma/pull/3710 "PR by @joshuay03, merged 2025-08-28"
2448
+ [#3709]:https://github.com/puma/puma/pull/3709 "PR by @MSP-Greg, merged 2025-08-28"
2449
+ [#3708]:https://github.com/puma/puma/issues/3708 "Issue by @schneems, closed 2025-08-28"
2450
+ [#3616]:https://github.com/puma/puma/pull/3616 "PR by @joshuay03, merged 2025-08-25"
2451
+ [#3635]:https://github.com/puma/puma/pull/3635 "PR by @LevitatingBusinessMan, merged 2025-05-08"
2452
+ [#3572]:https://github.com/puma/puma/pull/3572 "PR by @barthez, merged 2025-02-06"
2453
+ [#3601]:https://github.com/puma/puma/pull/3601 "PR by @joshuay03, merged 2025-01-31"
2454
+ [#3586]:https://github.com/puma/puma/pull/3586 "PR by @MSP-Greg, merged 2025-02-03"
2455
+ [#3598]:https://github.com/puma/puma/pull/3598 "PR by @joshuay03, merged 2025-01-31"
2456
+ [#3680]:https://github.com/puma/puma/pull/3680 "PR by @byroot, merged 2025-07-31"
2153
2457
  [#3570]:https://github.com/puma/puma/pull/3570 "PR by @mohamedhafez, merged 2024-12-30"
2154
2458
  [#3567]:https://github.com/puma/puma/issues/3567 "Issue by @mohamedhafez, closed 2024-12-30"
2155
2459
  [#3383]:https://github.com/puma/puma/pull/3383 "PR by @joshuay03, merged 2024-11-29"
@@ -2748,7 +3052,7 @@ be added back in a future date when a java Puma::MiniSSL is added.
2748
3052
  [#1022]:https://github.com/puma/puma/issues/1022 "Issue by @AKovtunov, closed 2017-08-16"
2749
3053
  [#958]:https://github.com/puma/puma/issues/958 "Issue by @lalitlogical, closed 2016-04-23"
2750
3054
  [#782]:https://github.com/puma/puma/issues/782 "Issue by @Tonkpils, closed 2016-07-19"
2751
- [#1010]:https://github.com/puma/puma/issues/1010 "Issue by @mneumark, closed 2016-07-19"
3055
+ [#1010]:https://github.com/puma/puma/issues/1010 "Issue by @mirineumark, closed 2016-07-19"
2752
3056
  [#959]:https://github.com/puma/puma/issues/959 "Issue by @mwpastore, closed 2016-04-22"
2753
3057
  [#840]:https://github.com/puma/puma/issues/840 "Issue by @marisawallace, closed 2016-04-07"
2754
3058
  [#1007]:https://github.com/puma/puma/pull/1007 "PR by @willnet, merged 2016-06-24"
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  <p align="center">
2
- <img src="https://puma.io/images/logos/puma-logo-large.png">
2
+ <img src="docs/images/standard-logo.svg" alt="Puma logo">
3
3
  </p>
4
4
 
5
5
  # Puma: A Ruby Web Server Built For Parallelism
6
6
 
7
- [![Actions](https://github.com/puma/puma/workflows/Tests/badge.svg?branch=master)](https://github.com/puma/puma/actions?query=workflow%3ATests)
8
- [![Code Climate](https://codeclimate.com/github/puma/puma.svg)](https://codeclimate.com/github/puma/puma)
9
- [![StackOverflow](https://img.shields.io/badge/stackoverflow-Puma-blue.svg)]( https://stackoverflow.com/questions/tagged/puma )
7
+ [![Actions](https://github.com/puma/puma/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/puma/puma/actions/workflows/tests.yml?query=branch%3Amain)
10
8
 
11
9
  Puma is a **simple, fast, multi-threaded, and highly parallel HTTP 1.1 server for Ruby/Rack applications**.
12
10
 
@@ -82,10 +80,10 @@ $ bundle exec puma
82
80
 
83
81
  ## Configuration
84
82
 
85
- Puma provides numerous options. Consult `puma -h` (or `puma --help`) for a full list of CLI options, or see `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb).
83
+ Puma provides numerous options. Consult `puma -h` (or `puma --help`) for a full list of CLI options, or see `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/main/lib/puma/dsl.rb).
86
84
 
87
85
  You can also find several configuration examples as part of the
88
- [test](https://github.com/puma/puma/tree/master/test/config) suite.
86
+ [test](https://github.com/puma/puma/tree/main/test/config) suite.
89
87
 
90
88
  For debugging purposes, you can set the environment variable `PUMA_LOG_CONFIG` with a value
91
89
  and the loaded configuration will be printed as part of the boot process.
@@ -102,9 +100,9 @@ Puma will automatically scale the number of threads, from the minimum until it c
102
100
 
103
101
  Be aware that additionally Puma creates threads on its own for internal purposes (e.g. handling slow clients). So, even if you specify -t 1:1, expect around 7 threads created in your application.
104
102
 
105
- ### Clustered mode
103
+ ### Cluster mode
106
104
 
107
- Puma also offers "clustered mode". Clustered mode `fork`s workers from a master process. Each child process still has its own thread pool. You can tune the number of workers with the `-w` (or `--workers`) flag:
105
+ Puma also offers "cluster mode". Cluster mode `fork`s workers from a master process. Each child process still has its own thread pool. You can tune the number of workers with the `-w` (or `--workers`) flag:
108
106
 
109
107
  ```
110
108
  $ puma -t 8:32 -w 3
@@ -116,15 +114,24 @@ Or with the `WEB_CONCURRENCY` environment variable:
116
114
  $ WEB_CONCURRENCY=3 puma -t 8:32
117
115
  ```
118
116
 
119
- Note that threads are still used in clustered mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total, with 16 in each worker process.
117
+ When using a config file, most applications can simply set `workers :auto` (requires the `concurrent-ruby` gem) to match the number of worker processes to the available processors:
120
118
 
121
- If the `WEB_CONCURRENCY` environment variable is set to `"auto"` and the `concurrent-ruby` gem is available in your application, Puma will set the worker process count to the result of [available processors](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html#available_processor_count-class_method).
119
+ ```ruby
120
+ # config/puma.rb
121
+ workers :auto
122
+ ```
123
+
124
+ See [`workers :auto` gotchas](lib/puma/dsl.rb).
122
125
 
123
- For an in-depth discussion of the tradeoffs of thread and process count settings, [see our docs](https://github.com/puma/puma/blob/9282a8efa5a0c48e39c60d22ca70051a25df9f55/docs/kubernetes.md#workers-per-pod-and-other-config-issues).
126
+ Note that threads are still used in cluster mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total, with 16 in each worker process.
124
127
 
125
- In clustered mode, Puma can "preload" your application. This loads all the application code *prior* to forking. Preloading reduces total memory usage of your application via an operating system feature called [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write).
128
+ If `workers` is set to `:auto`, or the `WEB_CONCURRENCY` environment variable is set to `"auto"`, and the `concurrent-ruby` gem is available in your application, Puma will set the worker process count to the result of [available processors](https://msp-greg.github.io/concurrent-ruby/Concurrent.html#available_processor_count-class_method).
126
129
 
127
- If the `WEB_CONCURRENCY` environment variable is set to a value > 1 (and `--prune-bundler` has not been specified), preloading will be enabled by default. Otherwise, you can use the `--preload` flag from the command line:
130
+ For an in-depth discussion of the tradeoffs of thread and process count settings, [see our docs](docs/deployment.md).
131
+
132
+ In cluster mode, Puma can "preload" your application. This loads all the application code *prior* to forking. Preloading reduces total memory usage of your application via an operating system feature called [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write).
133
+
134
+ If the number of workers is greater than 1 (and `--prune-bundler` has not been specified), preloading will be enabled by default. Otherwise, you can use the `--preload` flag from the command line:
128
135
 
129
136
  ```
130
137
  $ puma -w 3 --preload
@@ -140,10 +147,10 @@ preload_app!
140
147
 
141
148
  Preloading can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and preloading copies the code of master into the workers.
142
149
 
143
- #### Clustered mode hooks
150
+ #### Cluster mode hooks
144
151
 
145
- When using clustered mode, Puma's configuration DSL provides `before_fork` and `on_worker_boot`
146
- hooks to run code when the master process forks and child workers are booted respectively.
152
+ When using clustered mode, Puma's configuration DSL provides `before_fork`, `before_worker_boot`, and `after_worker_shutdown`
153
+ hooks to run code when the master process forks, the child workers are booted, and after each child worker exits respectively.
147
154
 
148
155
  It is recommended to use these hooks with `preload_app!`, otherwise constants loaded by your
149
156
  application (such as `Rails`) will not be available inside the hooks.
@@ -154,16 +161,21 @@ before_fork do
154
161
  # Add code to run inside the Puma master process before it forks a worker child.
155
162
  end
156
163
 
157
- on_worker_boot do
164
+ before_worker_boot do
158
165
  # Add code to run inside the Puma worker process after forking.
159
166
  end
167
+
168
+ after_worker_shutdown do |worker_handle|
169
+ # Add code to run inside the Puma master process after a worker exits. `worker.process_status` can be used to get the
170
+ # `Process::Status` of the exited worker.
171
+ end
160
172
  ```
161
173
 
162
- In addition, there is an `on_refork` and `after_refork` hooks which are used only in [`fork_worker` mode](docs/fork_worker.md),
174
+ In addition, there is an `before_refork` and `after_refork` hooks which are used only in [`fork_worker` mode](docs/fork_worker.md),
163
175
  when the worker 0 child process forks a grandchild worker:
164
176
 
165
177
  ```ruby
166
- on_refork do
178
+ before_refork do
167
179
  # Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
168
180
  # child process before it forks a grandchild worker.
169
181
  end
@@ -176,7 +188,7 @@ after_refork do
176
188
  end
177
189
  ```
178
190
 
179
- Importantly, note the following considerations when Ruby forks a child process:
191
+ Importantly, note the following considerations when Ruby forks a child process:
180
192
 
181
193
  1. File descriptors such as network sockets **are** copied from the parent to the forked
182
194
  child process. Dual-use of the same sockets by parent and child will result in I/O conflicts
@@ -190,29 +202,29 @@ Therefore, we recommend the following:
190
202
 
191
203
  1. If possible, do not establish any socket connections (HTTP, database connections, etc.)
192
204
  inside Puma's master process when booting.
193
- 2. If (1) is not possible, use `before_fork` and `on_refork` to disconnect the parent's socket
205
+ 2. If (1) is not possible, use `before_fork` and `before_refork` to disconnect the parent's socket
194
206
  connections when forking, so that they are not accidentally copied to the child process.
195
- 3. Use `on_worker_boot` to restart any background threads on the forked child.
207
+ 3. Use `before_worker_boot` to restart any background threads on the forked child.
196
208
  4. Use `after_refork` to restart any background threads on the parent.
197
209
 
198
210
  #### Master process lifecycle hooks
199
211
 
200
- Puma's configuration DSL provides master process lifecycle hooks `on_booted`, `on_restart`, and `on_stopped`
212
+ Puma's configuration DSL provides master process lifecycle hooks `after_booted`, `before_restart`, and `after_stopped`
201
213
  which may be used to specify code blocks to run on each event:
202
214
 
203
215
  ```ruby
204
216
  # config/puma.rb
205
- on_booted do
217
+ after_booted do
206
218
  # Add code to run in the Puma master process after it boots,
207
219
  # and also after a phased restart completes.
208
220
  end
209
221
 
210
- on_restart do
222
+ before_restart do
211
223
  # Add code to run in the Puma master process when it receives
212
224
  # a restart command but before it restarts.
213
225
  end
214
226
 
215
- on_stopped do
227
+ after_stopped do
216
228
  # Add code to run in the Puma master process when it receives
217
229
  # a stop command but before it shuts down.
218
230
  end
@@ -221,7 +233,7 @@ end
221
233
  ### Error handling
222
234
 
223
235
  If Puma encounters an error outside of the context of your application, it will respond with a 400/500 and a simple
224
- textual error message (see `Puma::Server#lowlevel_error` or [server.rb](https://github.com/puma/puma/blob/master/lib/puma/server.rb)).
236
+ textual error message (see `Puma::Server#lowlevel_error` or [server.rb](https://github.com/puma/puma/blob/main/lib/puma/server.rb)).
225
237
  You can specify custom behavior for this scenario. For example, you can report the error to your third-party
226
238
  error-tracking service (in this example, [rollbar](https://rollbar.com)):
227
239
 
@@ -380,7 +392,7 @@ Puma has a built-in status and control app that can be used to query and control
380
392
  $ puma --control-url tcp://127.0.0.1:9293 --control-token foo
381
393
  ```
382
394
 
383
- Puma will start the control server on localhost port 9293. All requests to the control server will need to include control token (in this case, `token=foo`) as a query parameter. This allows for simple authentication. Check out `Puma::App::Status` or [status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to see what the status app has available.
395
+ Puma will start the control server on localhost port 9293. All requests to the control server will need to include control token (in this case, `token=foo`) as a query parameter. This allows for simple authentication. Check out `Puma::App::Status` or [status.rb](https://github.com/puma/puma/blob/main/lib/puma/app/status.rb) to see what the status app has available.
384
396
 
385
397
  You can also interact with the control server via `pumactl`. This command will restart Puma:
386
398
 
@@ -412,7 +424,7 @@ $ puma -C "-"
412
424
 
413
425
  The other side-effects of setting the environment are whether to show stack traces (in `development` or `test`), and setting RACK_ENV may potentially affect middleware looking for this value to change their behavior. The default puma RACK_ENV value is `development`. You can see all config default values in `Puma::Configuration#puma_default_options` or [configuration.rb](https://github.com/puma/puma/blob/61c6213fbab/lib/puma/configuration.rb#L182-L204).
414
426
 
415
- Check out `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb) to see all available options.
427
+ Check out `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/main/lib/puma/dsl.rb) to see all available options.
416
428
 
417
429
  ## Restart
418
430
 
@@ -432,19 +444,6 @@ Some platforms do not support all Puma features.
432
444
  * **Windows**: Cluster mode is not supported due to a lack of fork(2).
433
445
  * **Kubernetes**: The way Kubernetes handles pod shutdowns interacts poorly with server processes implementing graceful shutdown, like Puma. See the [kubernetes section of the documentation](docs/kubernetes.md) for more details.
434
446
 
435
- ## Known Bugs
436
-
437
- For MRI versions 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 and 2.4.1, you may see ```stream closed in another thread (IOError)```. It may be caused by a [Ruby bug](https://bugs.ruby-lang.org/issues/13632). It can be fixed with the gem https://rubygems.org/gems/stopgap_13632:
438
-
439
- ```ruby
440
- if %w(2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1).include? RUBY_VERSION
441
- begin
442
- require 'stopgap_13632'
443
- rescue LoadError
444
- end
445
- end
446
- ```
447
-
448
447
  ## Deployment
449
448
 
450
449
  * Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).