Add tests for:
- Worker liveness reporting to arbiter via WorkerTmp
- SIGTERM graceful shutdown behavior
- SIGQUIT immediate shutdown behavior
- Worker-arbiter integration (parent death detection, timeout)
- Signal interaction edge cases (multiple signals, ordering)
These tests ensure the gthread worker properly:
- Calls notify() in the main loop for arbiter heartbeat
- Handles SIGTERM by setting alive=False and waking the poller
- Handles SIGQUIT by immediately shutting down the thread pool
- Drains connections during graceful shutdown within timeout
- Cleans up resources properly on exit
Replace RLock-based synchronization with a pipe-based method queue
for lock-free coordination between worker threads and main thread.
Key changes:
- Add PollableMethodQueue class using os.pipe() for wake-up signaling
- Non-blocking pipe (both ends) for BSD compatibility (FreeBSD, OpenBSD)
- Unified event loop using single poller.select() - no more futures.wait()
- Better graceful shutdown with connection draining within grace period
- Rename _keep to keepalived_conns, remove _lock entirely
- Add handle_exit() for SIGTERM, improve handle_quit() for SIGQUIT
- Add set_accept_enabled() for dynamic connection acceptance control
- Add wait_for_and_dispatch_events() with EINTR handling
Performance improvement: ~8% at high concurrency due to reduced
lock contention and non-blocking pipe operations.
Tests: 40 tests covering PollableMethodQueue, graceful shutdown,
keepalive management, error handling, and BSD compatibility.
Fixes#3146Closes#3157
This commit addresses three issues with the gthread worker:
1. Request body handling on keepalive
- Add finish_body() method to Parser to discard unread body bytes
- Call it before returning connections to the poller
- Prevents socket appearing readable due to leftover body
Fixes#3301
2. Timeout reliability with monotonic clock
- Replace time.time() with time.monotonic() in set_timeout()
- Replace time.time() with time.monotonic() in murder_keepalived()
- Prevents timeout issues caused by NTP adjustments
3. SSL error handling
- Move conn.init() from enqueue_req() to handle()
- SSL handshake now runs in worker thread, not main thread
- ENOTCONN errors during ssl_wrap_socket are caught per-connection
- Prevents entire worker crashes on SSL handshake failures
Also adds comprehensive unit tests for the gthread worker.
Closes#3303Closes#3308