Skip to content

v0.0.5 - Network resilience and protocol hardening

Choose a tag to compare

@Kludex Kludex released this 13 Aug 12:03
· 41 commits to main since this release
897813c

🌊 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, and ENOMEM instead 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 calling start_serving() or serve_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 as None, 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 flowinfo or scope_id values 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