Method: Puma::Server#reactor_wakeup
- Defined in:
- lib/puma/server.rb
#reactor_wakeup(client) ⇒ Object
This method is called from the Reactor thread when a queued Client receives data, times out, or when the Reactor is shutting down.
While the code lives in the Server, the logic is executed on the reactor thread, independently from the server.
It is responsible for ensuring that a request has been completely received before it starts to be processed by the ThreadPool. This may be known as read buffering. If read buffering is not done, and no other read buffering is performed (such as by an application server such as nginx) then the application would be subject to a slow client attack.
For a graphical representation of how the request buffer works see [architecture.md](github.com/puma/puma/blob/master/docs/architecture.md#connection-pipeline).
The method checks to see if it has the full header and body with the ‘Puma::Client#try_to_finish` method. If the full request has been sent, then the request is passed to the ThreadPool (`@thread_pool << client`) so that a “worker thread” can pick up the request and begin to execute application logic. The Client is then removed from the reactor (return `true`).
If a client object times out, a 408 response is written, its connection is closed, and the object is removed from the reactor (return ‘true`).
If the Reactor is shutting down, all Clients are either timed out or passed to the ThreadPool, depending on their current state (#can_close?).
Otherwise, if the full request is not ready then the client will remain in the reactor (return ‘false`). When the client sends more data to the socket the `Puma::Client` object will wake up and again be checked to see if it’s ready to be passed to the thread pool.
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/puma/server.rb', line 319 def reactor_wakeup(client) shutdown = !@queue_requests if client.try_to_finish || (shutdown && !client.can_close?) @thread_pool << client elsif shutdown || client.timeout == 0 client.timeout! else client.set_timeout(@first_data_timeout) false end rescue StandardError => e client_error(e, client) close_client_safely(client) true end |