puma 3.0.0.rc1 → 5.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/{History.txt → History.md} +703 -70
  3. data/LICENSE +23 -20
  4. data/README.md +173 -163
  5. data/docs/architecture.md +37 -0
  6. data/{DEPLOYMENT.md → docs/deployment.md} +28 -6
  7. data/docs/fork_worker.md +31 -0
  8. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  9. data/docs/images/puma-connection-flow.png +0 -0
  10. data/docs/images/puma-general-arch.png +0 -0
  11. data/docs/jungle/README.md +13 -0
  12. data/docs/jungle/rc.d/README.md +74 -0
  13. data/docs/jungle/rc.d/puma +61 -0
  14. data/docs/jungle/rc.d/puma.conf +10 -0
  15. data/{tools → docs}/jungle/upstart/README.md +0 -0
  16. data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
  17. data/{tools → docs}/jungle/upstart/puma.conf +1 -1
  18. data/docs/nginx.md +2 -2
  19. data/docs/plugins.md +38 -0
  20. data/docs/restart.md +41 -0
  21. data/docs/signals.md +57 -3
  22. data/docs/systemd.md +228 -0
  23. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  24. data/ext/puma_http11/extconf.rb +16 -0
  25. data/ext/puma_http11/http11_parser.c +287 -468
  26. data/ext/puma_http11/http11_parser.h +1 -0
  27. data/ext/puma_http11/http11_parser.java.rl +21 -37
  28. data/ext/puma_http11/http11_parser.rl +10 -9
  29. data/ext/puma_http11/http11_parser_common.rl +4 -4
  30. data/ext/puma_http11/mini_ssl.c +159 -10
  31. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  32. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +99 -132
  33. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +30 -6
  34. data/ext/puma_http11/puma_http11.c +6 -38
  35. data/lib/puma.rb +25 -5
  36. data/lib/puma/accept_nonblock.rb +7 -1
  37. data/lib/puma/app/status.rb +53 -26
  38. data/lib/puma/binder.rb +150 -119
  39. data/lib/puma/cli.rb +56 -38
  40. data/lib/puma/client.rb +277 -80
  41. data/lib/puma/cluster.rb +326 -130
  42. data/lib/puma/commonlogger.rb +21 -20
  43. data/lib/puma/configuration.rb +160 -161
  44. data/lib/puma/const.rb +50 -47
  45. data/lib/puma/control_cli.rb +104 -63
  46. data/lib/puma/detect.rb +13 -1
  47. data/lib/puma/dsl.rb +463 -114
  48. data/lib/puma/events.rb +22 -13
  49. data/lib/puma/io_buffer.rb +9 -5
  50. data/lib/puma/jruby_restart.rb +2 -59
  51. data/lib/puma/launcher.rb +195 -105
  52. data/lib/puma/minissl.rb +110 -4
  53. data/lib/puma/minissl/context_builder.rb +76 -0
  54. data/lib/puma/null_io.rb +9 -14
  55. data/lib/puma/plugin.rb +32 -12
  56. data/lib/puma/plugin/tmp_restart.rb +19 -6
  57. data/lib/puma/rack/builder.rb +7 -5
  58. data/lib/puma/rack/urlmap.rb +11 -8
  59. data/lib/puma/rack_default.rb +2 -0
  60. data/lib/puma/reactor.rb +242 -32
  61. data/lib/puma/runner.rb +41 -30
  62. data/lib/puma/server.rb +265 -183
  63. data/lib/puma/single.rb +22 -63
  64. data/lib/puma/state_file.rb +9 -2
  65. data/lib/puma/thread_pool.rb +179 -68
  66. data/lib/puma/util.rb +3 -11
  67. data/lib/rack/handler/puma.rb +60 -11
  68. data/tools/Dockerfile +16 -0
  69. data/tools/trickletest.rb +1 -2
  70. metadata +35 -99
  71. data/COPYING +0 -55
  72. data/Gemfile +0 -13
  73. data/Manifest.txt +0 -79
  74. data/Rakefile +0 -158
  75. data/docs/config.md +0 -0
  76. data/ext/puma_http11/io_buffer.c +0 -155
  77. data/lib/puma/capistrano.rb +0 -94
  78. data/lib/puma/compat.rb +0 -18
  79. data/lib/puma/convenient.rb +0 -23
  80. data/lib/puma/daemon_ext.rb +0 -31
  81. data/lib/puma/delegation.rb +0 -11
  82. data/lib/puma/java_io_buffer.rb +0 -45
  83. data/lib/puma/rack/backports/uri/common_18.rb +0 -56
  84. data/lib/puma/rack/backports/uri/common_192.rb +0 -52
  85. data/lib/puma/rack/backports/uri/common_193.rb +0 -29
  86. data/lib/puma/tcp_logger.rb +0 -32
  87. data/puma.gemspec +0 -52
  88. data/tools/jungle/README.md +0 -9
  89. data/tools/jungle/init.d/README.md +0 -54
  90. data/tools/jungle/init.d/puma +0 -394
  91. data/tools/jungle/init.d/run-puma +0 -3
@@ -0,0 +1,37 @@
1
+ # Architecture
2
+
3
+ ## Overview
4
+
5
+ ![http://bit.ly/2iJuFky](images/puma-general-arch.png)
6
+
7
+ Puma is a threaded web server, processing requests across a TCP or UNIX socket.
8
+
9
+ Workers accept connections from the socket and a thread in the worker's thread pool processes the client's request.
10
+
11
+ Clustered mode is shown/discussed here. Single mode is analogous to having a single worker process.
12
+
13
+ ## Connection pipeline
14
+
15
+ ![http://bit.ly/2zwzhEK](images/puma-connection-flow.png)
16
+
17
+ * Upon startup, Puma listens on a TCP or UNIX socket.
18
+ * The backlog of this socket is configured (with a default of 1024), determining how many established but unaccepted connections can exist concurrently.
19
+ * This socket backlog is distinct from the "backlog" of work as reported by the control server stats. The latter is the number of connections in that worker's "todo" set waiting for a worker thread.
20
+ * By default, a single, separate thread is used to receive HTTP requests across the socket.
21
+ * When at least one worker thread is available for work, a connection is accepted and placed in this request buffer
22
+ * This thread waits for entire HTTP requests to be received over the connection
23
+ * The time spent waiting for the HTTP request body to be received is exposed to the Rack app as `env['puma.request_body_wait']` (milliseconds)
24
+ * Once received, the connection is pushed into the "todo" set
25
+ * Worker threads pop work off the "todo" set for processing
26
+ * The thread processes the request via the rack application (which generates the HTTP response)
27
+ * The thread writes the response to the connection
28
+ * Finally, the thread become available to process another connection in the "todo" set
29
+
30
+ ### Disabling `queue_requests`
31
+
32
+ ![http://bit.ly/2zxCJ1Z](images/puma-connection-flow-no-reactor.png)
33
+
34
+ The `queue_requests` option is `true` by default, enabling the separate thread used to buffer requests as described above.
35
+
36
+ If set to `false`, this buffer will not be used for connections while waiting for the request to arrive.
37
+ In this mode, when a connection is accepted, it is added to the "todo" queue immediately, and a worker will synchronously do any waiting necessary to read the HTTP request from the socket.
@@ -27,7 +27,7 @@ Here are some rules of thumb:
27
27
  * Use cluster mode and set the number of workers to 1.5x the number of cpu cores
28
28
  in the machine, minimum 2.
29
29
  * Set the number of threads to desired concurrent requests / number of workers.
30
- Puma defaults to 8 and that's a decent number.
30
+ Puma defaults to 16 and that's a decent number.
31
31
 
32
32
  #### Migrating from Unicorn
33
33
 
@@ -38,23 +38,45 @@ Here are some rules of thumb:
38
38
  * As you grow more confident in the thread safety of your app, you can tune the
39
39
  workers down and the threads up.
40
40
 
41
+ #### Ubuntu / Systemd (Systemctl) Installation
42
+
43
+ See [systemd.md](systemd.md)
44
+
41
45
  #### Worker utilization
42
46
 
43
- **How do you know if you're got enough (or too many workers)?**
47
+ **How do you know if you've got enough (or too many workers)?**
44
48
 
45
49
  A good question. Due to MRI's GIL, only one thread can be executing Ruby code at a time.
46
50
  But since so many apps are waiting on IO from DBs, etc., they can utilize threads
47
51
  to make better use of the process.
48
52
 
49
53
  The rule of thumb is you never want processes that are pegged all the time. This
50
- means that there is more work to do that the process can get through. On the other
54
+ means that there is more work to do than the process can get through. On the other
51
55
  hand, if you have processes that sit around doing nothing, then they're just eating
52
56
  up resources.
53
57
 
54
- Watching your CPU utilization over time and aim for about 70% on average. This means
58
+ Watch your CPU utilization over time and aim for about 70% on average. This means
55
59
  you've got capacity still but aren't starving threads.
56
60
 
57
- ## Daemonizing
61
+ **Measuring utilization**
62
+
63
+ Using a timestamp header from an upstream proxy server (eg. nginx or haproxy), it's
64
+ possible to get an indication of how long requests have been waiting for a Puma
65
+ thread to become available.
66
+
67
+ * Have your upstream proxy set a header with the time it received the request:
68
+ * nginx: `proxy_set_header X-Request-Start "${msec}";`
69
+ * haproxy: `http-request set-header X-Request-Start "%t";`
70
+ * In your Rack middleware, determine the amount of time elapsed since `X-Request-Start`.
71
+ * To improve accuracy, you will want to subtract time spent waiting for slow clients:
72
+ * `env['puma.request_body_wait']` contains the number of milliseconds Puma spent
73
+ waiting for the client to send the request body.
74
+ * haproxy: `%Th` (TLS handshake time) and `%Ti` (idle time before request) can
75
+ can also be added as headers.
76
+
77
+ ## Should I daemonize?
78
+
79
+ Daemonization was removed in Puma 5.0. For alternatives, continue reading.
58
80
 
59
81
  I prefer to not daemonize my servers and use something like `runit` or `upstart` to
60
82
  monitor them as child processes. This gives them fast response to crashes and
@@ -62,7 +84,7 @@ makes it easy to figure out what is going on. Additionally, unlike `unicorn`,
62
84
  puma does not require daemonization to do zero-downtime restarts.
63
85
 
64
86
  I see people using daemonization because they start puma directly via capistrano
65
- task and thus want it to live on past the `cap deploy`. To this people I said:
87
+ task and thus want it to live on past the `cap deploy`. To these people I say:
66
88
  You need to be using a process monitor. Nothing is making sure puma stays up in
67
89
  this scenario! You're just waiting for something weird to happen, puma to die,
68
90
  and to get paged at 3am. Do yourself a favor, at least the process monitoring
@@ -0,0 +1,31 @@
1
+ # Fork-Worker Cluster Mode [Experimental]
2
+
3
+ Puma 5 introduces an experimental new cluster-mode configuration option, `fork_worker` (`--fork-worker` from the CLI). This mode causes Puma to fork additional workers from worker 0, instead of directly from the master process:
4
+
5
+ ```
6
+ 10000 \_ puma 4.3.3 (tcp://0.0.0.0:9292) [puma]
7
+ 10001 \_ puma: cluster worker 0: 10000 [puma]
8
+ 10002 \_ puma: cluster worker 1: 10000 [puma]
9
+ 10003 \_ puma: cluster worker 2: 10000 [puma]
10
+ 10004 \_ puma: cluster worker 3: 10000 [puma]
11
+ ```
12
+
13
+ Similar to the `preload_app!` option, the `fork_worker` option allows your application to be initialized only once for copy-on-write memory savings, and it has two additional advantages:
14
+
15
+ 1. **Compatible with phased restart.** Because the master process itself doesn't preload the application, this mode works with phased restart (`SIGUSR1` or `pumactl phased-restart`). When worker 0 reloads as part of a phased restart, it initializes a new copy of your application first, then the other workers reload by forking from this new worker already containing the new preloaded application.
16
+
17
+ This allows a phased restart to complete as quickly as a hot restart (`SIGUSR2` or `pumactl restart`), while still minimizing downtime by staggering the restart across cluster workers.
18
+
19
+ 2. **'Refork' for additional copy-on-write improvements in running applications.** Fork-worker mode introduces a new `refork` command that re-loads all nonzero workers by re-forking them from worker 0.
20
+
21
+ This command can potentially improve memory utilization in large or complex applications that don't fully pre-initialize on startup, because the re-forked workers can share copy-on-write memory with a worker that has been running for a while and serving requests.
22
+
23
+ You can trigger a refork by sending the cluster the `SIGURG` signal or running the `pumactl refork` command at any time. A refork will also automatically trigger once, after a certain number of requests have been processed by worker 0 (default 1000). To configure the number of requests before the auto-refork, pass a positive integer argument to `fork_worker` (e.g., `fork_worker 1000`), or `0` to disable.
24
+
25
+ ### Limitations
26
+
27
+ - This mode is still very experimental so there may be bugs or edge-cases, particularly around expected behavior of existing hooks. Please open a [bug report](https://github.com/puma/puma/issues/new?template=bug_report.md) if you encounter any issues.
28
+
29
+ - In order to fork new workers cleanly, worker 0 shuts down its server and stops serving requests so there are no open file descriptors or other kinds of shared global state between processes, and to maximize copy-on-write efficiency across the newly-forked workers. This may temporarily reduce total capacity of the cluster during a phased restart / refork.
30
+
31
+ In a cluster with `n` workers, a normal phased restart stops and restarts workers one by one while the application is loaded in each process, so `n-1` workers are available serving requests during the restart. In a phased restart in fork-worker mode, the application is first loaded in worker 0 while `n-1` workers are available, then worker 0 remains stopped while the rest of the workers are reloaded one by one, leaving only `n-2` workers to be available for a brief period of time. Reloading the rest of the workers should be quick because the application is preloaded at that point, but there may be situations where it can take longer (slow clients, long-running application code, slow worker-fork hooks, etc).
@@ -0,0 +1,13 @@
1
+ # Puma as a service
2
+
3
+ ## Upstart
4
+
5
+ See `/docs/jungle/upstart` for Ubuntu's upstart scripts.
6
+
7
+ ## Systemd
8
+
9
+ See [/docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md).
10
+
11
+ ## rc.d
12
+
13
+ See `/docs/jungle/rc.d` for FreeBSD's rc.d scripts
@@ -0,0 +1,74 @@
1
+ # Puma as a service using rc.d
2
+
3
+ Manage multilpe Puma servers as services on one box using FreeBSD's rc.d service.
4
+
5
+ ## Dependencies
6
+
7
+ * `jq` - a command-line json parser is needed to parse the json in the config file
8
+
9
+ ## Installation
10
+
11
+ # Copy the puma script to the rc.d directory (make sure everyone has read/execute perms)
12
+ sudo cp puma /usr/local/etc/rc.d/
13
+
14
+ # Create an empty configuration file
15
+ sudo touch /usr/local/etc/puma.conf
16
+
17
+ # Enable the puma service
18
+ sudo echo 'puma_enable="YES"' >> /etc/rc.conf
19
+
20
+ ## Managing the jungle
21
+
22
+ Puma apps are referenced in /usr/local/etc/puma.conf by default.
23
+
24
+ Start the jungle running:
25
+
26
+ `service puma start`
27
+
28
+ This script will run at boot time.
29
+
30
+
31
+ You can also stop the jungle (stops ALL puma instances) by running:
32
+
33
+ `service puma stop`
34
+
35
+
36
+ To restart the jungle:
37
+
38
+ `service puma restart`
39
+
40
+ ## Conventions
41
+
42
+ * The script expects:
43
+ * a config file to exist under `config/puma.rb` in your app. E.g.: `/home/apps/my-app/config/puma.rb`.
44
+
45
+ You can always change those defaults by editing the scripts.
46
+
47
+ ## Here's what a minimal app's config file should have
48
+
49
+ ```
50
+ {
51
+ "servers" : [
52
+ {
53
+ "dir": "/path/to/rails/project",
54
+ "user": "deploy-user",
55
+ "ruby_version": "ruby.version",
56
+ "ruby_env": "rbenv"
57
+ }
58
+ ]
59
+ }
60
+ ```
61
+
62
+ ## Before starting...
63
+
64
+ You need to customise `puma.conf` to:
65
+
66
+ * Set the right user your app should be running on unless you want root to execute it!
67
+ * Set the directory of the app
68
+ * Set the ruby version to execute
69
+ * Set the ruby environment (currently set to rbenv, since that is the only ruby environment currently supported)
70
+ * Add additional server instances following the scheme in the example
71
+
72
+ ## Notes:
73
+
74
+ Only rbenv is currently supported.
@@ -0,0 +1,61 @@
1
+ #!/bin/sh
2
+ #
3
+
4
+ # PROVIDE: puma
5
+
6
+ . /etc/rc.subr
7
+
8
+ name="puma"
9
+ start_cmd="puma_start"
10
+ stop_cmd="puma_stop"
11
+ restart_cmd="puma_restart"
12
+ rcvar=puma_enable
13
+ required_files=/usr/local/etc/puma.conf
14
+
15
+ puma_start()
16
+ {
17
+ server_count=$(/usr/local/bin/jq ".servers[] .ruby_env" /usr/local/etc/puma.conf | wc -l)
18
+ i=0
19
+ while [ "$i" -lt "$server_count" ]; do
20
+ rb_env=$(/usr/local/bin/jq -r ".servers[$i].ruby_env" /usr/local/etc/puma.conf)
21
+ dir=$(/usr/local/bin/jq -r ".servers[$i].dir" /usr/local/etc/puma.conf)
22
+ user=$(/usr/local/bin/jq -r ".servers[$i].user" /usr/local/etc/puma.conf)
23
+ rb_ver=$(/usr/local/bin/jq -r ".servers[$i].ruby_version" /usr/local/etc/puma.conf)
24
+ case $rb_env in
25
+ "rbenv")
26
+ su - $user -c "cd $dir && rbenv shell $rb_ver && bundle exec puma -C $dir/config/puma.rb -d"
27
+ ;;
28
+ *)
29
+ ;;
30
+ esac
31
+ i=$(( i + 1 ))
32
+ done
33
+ }
34
+
35
+ puma_stop()
36
+ {
37
+ pkill ruby
38
+ }
39
+
40
+ puma_restart()
41
+ {
42
+ server_count=$(/usr/local/bin/jq ".servers[] .ruby_env" /usr/local/etc/puma.conf | wc -l)
43
+ i=0
44
+ while [ "$i" -lt "$server_count" ]; do
45
+ rb_env=$(/usr/local/bin/jq -r ".servers[$i].ruby_env" /usr/local/etc/puma.conf)
46
+ dir=$(/usr/local/bin/jq -r ".servers[$i].dir" /usr/local/etc/puma.conf)
47
+ user=$(/usr/local/bin/jq -r ".servers[$i].user" /usr/local/etc/puma.conf)
48
+ rb_ver=$(/usr/local/bin/jq -r ".servers[$i].ruby_version" /usr/local/etc/puma.conf)
49
+ case $rb_env in
50
+ "rbenv")
51
+ su - $user -c "cd $dir && pkill ruby && rbenv shell $ruby_version && bundle exec puma -C $dir/config/puma.rb -d"
52
+ ;;
53
+ *)
54
+ ;;
55
+ esac
56
+ i=$(( i + 1 ))
57
+ done
58
+ }
59
+
60
+ load_rc_config $name
61
+ run_rc_command "$1"
@@ -0,0 +1,10 @@
1
+ {
2
+ "servers" : [
3
+ {
4
+ "dir": "/path/to/rails/project",
5
+ "user": "deploy-user",
6
+ "ruby_version": "ruby.version",
7
+ "ruby_env": "rbenv"
8
+ }
9
+ ]
10
+ }
File without changes
@@ -4,7 +4,7 @@
4
4
  # allows you to manage multiple Puma instances with
5
5
  # Upstart, Ubuntu's native service management tool.
6
6
  #
7
- # See workers.conf for how to manage all Puma instances at once.
7
+ # See puma-manager.conf for how to manage all Puma instances at once.
8
8
  #
9
9
  # Save this config as /etc/init/puma.conf then manage puma with:
10
10
  # sudo start puma app=PATH_TO_APP
@@ -34,7 +34,7 @@ server {
34
34
  proxy_set_header Host $http_host;
35
35
 
36
36
  # If the file exists as a static file serve it directly without
37
- # running all the other rewite tests on it
37
+ # running all the other rewrite tests on it
38
38
  if (-f $request_filename) {
39
39
  break;
40
40
  }
@@ -50,7 +50,7 @@ server {
50
50
  # this is the meat of the rack page caching config
51
51
  # it adds .html to the end of the url and then checks
52
52
  # the filesystem for that file. If it exists, then we
53
- # rewite the url to have explicit .html on the end
53
+ # rewrite the url to have explicit .html on the end
54
54
  # and then send it on its way to the next config rule.
55
55
  # if there is no file on the fs then it sets all the
56
56
  # necessary headers and proxies to our upstream pumas
@@ -0,0 +1,38 @@
1
+ ## Plugins
2
+
3
+ Puma 3.0 added support for plugins that can augment configuration and service
4
+ operations.
5
+
6
+ 2 canonical plugins to look to aid in development of further plugins:
7
+
8
+ * [tmp\_restart](https://github.com/puma/puma/blob/master/lib/puma/plugin/tmp_restart.rb):
9
+ Restarts the server if the file `tmp/restart.txt` is touched
10
+ * [heroku](https://github.com/puma/puma-heroku/blob/master/lib/puma/plugin/heroku.rb):
11
+ Packages up the default configuration used by puma on Heroku
12
+
13
+ Plugins are activated in a puma configuration file (such as `config/puma.rb'`)
14
+ by adding `plugin "name"`, such as `plugin "heroku"`.
15
+
16
+ Plugins are activated based simply on path requirements so, activating the
17
+ `heroku` plugin will simply be doing `require "puma/plugin/heroku"`. This
18
+ allows gems to provide multiple plugins (as well as unrelated gems to provide
19
+ puma plugins).
20
+
21
+ The `tmp_restart` plugin is bundled with puma, so it can always be used.
22
+
23
+ To use the `heroku` plugin, add `puma-heroku` to your Gemfile or install it.
24
+
25
+ ### API
26
+
27
+ ## Server-wide hooks
28
+
29
+ Plugins can use a couple of hooks at server level: `start` and `config`.
30
+
31
+ `start` runs when the server has started and allows the plugin to start other
32
+ functionality to augment puma.
33
+
34
+ `config` runs when the server is being configured and is passed a `Puma::DSL`
35
+ object that can be used to add additional configuration.
36
+
37
+ Any public methods in `Puma::Plugin` are the public API that any plugin may
38
+ use.
@@ -0,0 +1,41 @@
1
+ # Restarts
2
+
3
+ To perform a restart, there are 3 builtin mechanisms:
4
+
5
+ * Send the `puma` process the `SIGUSR2` signal (normal restart)
6
+ * Send the `puma` process the `SIGUSR1` signal (restart in phases (a "rolling restart"), cluster mode only)
7
+ * Use the status server and issue `/restart`
8
+
9
+ No code is shared between the current and restarted process, so it should be safe to issue a restart any place where you would manually stop Puma and start it again.
10
+
11
+ If the new process is unable to load, it will simply exit. You should therefore run Puma under a process monitor (see below) when using it in production.
12
+
13
+ ### Normal vs Hot vs Phased Restart
14
+
15
+ A hot restart means that no requests will be lost while deploying your new code, since the server socket is kept open between restarts.
16
+
17
+ But beware, hot restart does not mean that the incoming requests won’t hang for multiple seconds while your new code has not fully deployed. If you need a zero downtime and zero hanging requests deploy, you must use phased restart.
18
+
19
+ When you run pumactl phased-restart, Puma kills workers one-by-one, meaning that at least another worker is still available to serve requests, which lead to zero hanging requests (yay!).
20
+
21
+ But again beware, upgrading an application sometimes involves upgrading the database schema. With phased restart, there may be a moment during the deployment where processes belonging to the previous version and processes belonging to the new version both exist at the same time. Any database schema upgrades you perform must therefore be backwards-compatible with the old application version.
22
+
23
+ If you perform a lot of database migrations, you probably should not use phased restart and use a normal/hot restart instead (`pumactl restart`). That way, no code is shared while deploying (in that case, `preload_app!` might help for quicker deployment, see ["Clustered Mode" in the README](../README.md#clustered-mode)).
24
+
25
+ **Note**: Hot and phased restarts are only available on MRI, not on JRuby. They are also unavailable on Windows servers.
26
+
27
+ ### Release Directory
28
+
29
+ If your symlink releases into a common working directory (i.e., `/current` from Capistrano), Puma won't pick up your new changes when running phased restarts without additional configuration. You should set your working directory within Puma's config to specify the directory it should use. This is a change from earlier versions of Puma (< 2.15) that would infer the directory for you.
30
+
31
+ ```ruby
32
+ # config/puma.rb
33
+
34
+ directory '/var/www/current'
35
+ ```
36
+
37
+ ### Cleanup Code
38
+
39
+ Puma isn't able to understand all the resources that your app may use, so it provides a hook in the configuration file you pass to `-C` called `on_restart`. The block passed to `on_restart` will be called, unsurprisingly, just before Puma restarts itself.
40
+
41
+ You should place code to close global log files, redis connections, etc. in this block so that their file descriptors don't leak into the restarted process. Failure to do so will result in slowly running out of descriptors and eventually obscure crashes as the server is restarted many times.
@@ -36,8 +36,62 @@ Puma cluster responds to these signals:
36
36
  - `TTIN` increment the worker count by 1
37
37
  - `TTOU` decrement the worker count by 1
38
38
  - `TERM` send `TERM` to worker. Worker will attempt to finish then exit.
39
- - `USR2` restart workers
40
- - `USR1` restart workers in phases, a rolling restart.
41
- - `HUP` reopen log files defined in stdout_redirect configuration parameter
39
+ - `USR2` restart workers. This also reloads puma configuration file, if there is one.
40
+ - `USR1` restart workers in phases, a rolling restart. This will not reload configuration file.
41
+ - `HUP` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
42
42
  - `INT` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
43
43
  - `CHLD`
44
+ - `URG` refork workers in phases from worker 0, if `fork_workers` option is enabled.
45
+
46
+ ## Callbacks order in case of different signals
47
+
48
+ ### Start application
49
+
50
+ ```
51
+ puma configuration file reloaded, if there is one
52
+ * Pruning Bundler environment
53
+ puma configuration file reloaded, if there is one
54
+
55
+ before_fork
56
+ on_worker_fork
57
+ after_worker_fork
58
+
59
+ Gemfile in context
60
+
61
+ on_worker_boot
62
+
63
+ Code of the app is loaded and running
64
+ ```
65
+
66
+ ### Send USR2
67
+
68
+ ```
69
+ on_worker_shutdown
70
+ on_restart
71
+
72
+ puma configuration file reloaded, if there is one
73
+
74
+ before_fork
75
+ on_worker_fork
76
+ after_worker_fork
77
+
78
+ Gemfile in context
79
+
80
+ on_worker_boot
81
+
82
+ Code of the app is loaded and running
83
+ ```
84
+
85
+ ### Send USR1
86
+
87
+ ```
88
+ on_worker_shutdown
89
+ on_worker_fork
90
+ after_worker_fork
91
+
92
+ Gemfile in context
93
+
94
+ on_worker_boot
95
+
96
+ Code of the app is loaded and running
97
+ ```