v0.0.5 - Network resilience and protocol hardening
🌊 Network resilience under pressure
zuvloop 0.0.5 hardens the paths that only become interesting when a server is busy, shutting down, upgrading to TLS, or running out of operating-system resources. It also turns musl and real aiohttp/uvicorn traffic into release gates.
pip install zuvloop==0.0.5- Accept loops now back off on
EMFILE,ENFILE,ENOBUFS, andENOMEMinstead of spinning and consuming a CPU core (#78, #88, #89). Recovery follows asyncio's retry model, remains safe after server closure, and cannot be bypassed by callingstart_serving()orserve_forever()again. - Python socket views are disarmed before libuv closes the native descriptor (#75). This closes a double-close race where another thread could reuse the descriptor number before delayed cleanup ran.
- Failed stream and datagram construction closes adopted sockets exactly once (#80), including protocol-factory failures and partial native adoption.
- Cancelling
serve_forever()now closes connected clients and waits for shutdown (#87), so cancellation no longer leaves accepted connections alive. - UNIX server cleanup always wakes
wait_closed()callers (#84), even when removing the socket path fails. - Datagram protocols stop receiving error and flow-control callbacks after close or abort (#77).
🔐 Protocol and native-boundary correctness
- Server-side
start_tls()carries already-buffered plaintext into TLS (#85). Proxy headers and a coalesced ClientHello can no longer strand handshake bytes in the replaced stream protocol. - Linux abstract UNIX datagram addresses round-trip with their exact identity (#86). Abstract names are exposed as
bytes, unnamed senders asNone, and the required libuv changes are preserved as a patch that is reapplied during vendor updates. - Socket addresses are validated before entering native structures (#81). Embedded NULs and out-of-range IPv6
flowinfoorscope_idvalues now fail in Python instead of being truncated or wrapped. - Invalid write-buffer limits fail before unsigned conversion (#79); valid low-only configurations still derive a safe high watermark.
- Infinite and extremely large timer delays are clamped safely (#76) across scheduling,
wait_for(), and metrics instrumentation. - PID reuse cannot lose a newer subprocess registration (#82) when a stale reaper callback finishes late.
🧪 Release confidence and portability
- aiohttp and uvicorn now run end to end in the normal test suite (#49), covering real protocol, flow-control, large-response, concurrency, and shutdown paths on
zuvloop.EventLoop. - The complete suite now runs under musl, and framework traffic runs under ReleaseSafe (#50). Published Alpine-compatible wheels are tested at runtime instead of only being cross-compiled.
- Timer fairness under sustained
call_soon_threadsafe()traffic now has a recorded CodSpeed baseline (#83) for the follow-up scheduler work. - Release workflows use the latest pinned checkout and artifact actions (#73).
Full changelog: v0.0.4...v0.0.5