MCPcopy
hub / github.com/benoitc/gunicorn / handle

Method handle

gunicorn/workers/gthread.py:446–514  ·  view source on GitHub ↗

Handle a request on a connection. Runs in a worker thread.

(self, conn)

Source from the content-addressed store, hash-verified

444 conn.close()
445
446 def handle(self, conn):
447 """Handle a request on a connection. Runs in a worker thread."""
448 req = None
449 try:
450 # For new connections (not yet initialized), wait for data with timeout
451 # to prevent slow clients from blocking thread pool slots indefinitely.
452 # Skip this for already-initialized connections (keepalive, deferred)
453 # since they're coming from the poller and data is already available.
454 if not conn.initialized and not conn.data_ready:
455 # Wait for data with timeout before committing this thread
456 if not conn.wait_for_data(DEFAULT_WORKER_DATA_TIMEOUT):
457 # No data within timeout - defer to poller
458 return _DEFER
459
460 # Always ensure blocking mode in worker thread.
461 # Critical for keepalive connections: the socket is set to non-blocking
462 # for the selector in finish_request(), but must be blocking for
463 # request/body reading to avoid SSLWantReadError on SSL connections.
464 conn.sock.setblocking(True)
465
466 # Initialize connection in worker thread to handle SSL errors gracefully
467 # (ENOTCONN from ssl_wrap_socket would crash main thread otherwise)
468 conn.init()
469
470 # HTTP/2 connections require special handling
471 if conn.is_http2:
472 return self.handle_http2(conn)
473
474 req = next(conn.parser)
475 if not req:
476 return False
477
478 # Handle the request
479 keepalive = self.handle_request(req, conn)
480 if keepalive:
481 # Discard any unread request body before keepalive to prevent
482 # the socket from appearing readable due to leftover bytes.
483 # Bound the drain by the worker data timeout: a stalled client
484 # must not keep this thread blocked.
485 drain_deadline = time.monotonic() + DEFAULT_WORKER_DATA_TIMEOUT
486 if not conn.parser.finish_body(deadline=drain_deadline):
487 # Abandon keepalive when the body could not be fully drained.
488 return False
489 return True
490 except http.errors.NoMoreData as e:
491 self.log.debug("Ignored premature client disconnection. %s", e)
492 except StopIteration as e:
493 self.log.debug("Closing connection. %s", e)
494 except ssl.SSLError as e:
495 if e.args[0] == ssl.SSL_ERROR_EOF:
496 self.log.debug("ssl connection closed")
497 conn.sock.close()
498 else:
499 self.log.debug("Error processing SSL request.")
500 self.handle_error(req, conn.sock, conn.client, e)
501 except OSError as e:
502 if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN):
503 self.log.exception("Socket error processing request.")

Callers

nothing calls this directly

Calls 10

handle_http2Method · 0.95
handle_requestMethod · 0.95
wait_for_dataMethod · 0.80
finish_bodyMethod · 0.80
handle_errorMethod · 0.80
setblockingMethod · 0.45
initMethod · 0.45
debugMethod · 0.45
closeMethod · 0.45
exceptionMethod · 0.45

Tested by

no test coverage detected