v0.0.4 - Security and lifecycle hardening
🔒 Security and ownership hardening
zuvloop 0.0.4 focuses on making native ownership boundaries match asyncio and CPython even under reentrancy, finalization, and subprocess edge cases.
pip install zuvloop==0.0.4- Mutable write buffers are snapshotted before
write()returns (#61). Exactbytesobjects retain the zero-copy path;bytearray, custom buffer exporters, and other potentially mutable inputs can no longer change queued network bytes after submission. - Subprocess strings reject embedded NULs (#59) rather than being silently truncated by libuv's C-string boundary.
- Linux subprocesses preserve
close_fdssemantics (#56). Unrelated inheritable descriptors stay out of children, including whenpass_fdsis used, and one bounded process-wide reaper bridges stdlib child exits back to the event loop. - Signal handlers and the wakeup fd have explicit per-loop ownership (#62). Finalizing an older loop can no longer reset a newer loop's process-global signal state; rollback is safe across deferred-finalizer races.
- Reentrant handle cancellation keeps vectorcall references alive (#64) without adding allocation or refcount work to every callback.
- DNS GC traversal stops when the native resolver reaper owns the requests (#60), removing a native use-after-free race during loop shutdown.
🧭 Asyncio compatibility and lifecycle fixes
- Reentrant
writelines()cannot queue bytes afterwrite_eof()(#67). - A failed metrics sampler start now restores running-loop and async-generator state (#65).
- Connected IPv6 datagram validation includes
flowinfo(#66). - A failed
uv_udp_openreports the original error without reopening a closing handle (#68). - Slow-callback telemetry skips call-graph formatting for completed tasks (#69).
- Self-pipe EOF unregisters the reader instead of leaving the loop in a busy spin (#70).
🏗️ Release and supply-chain controls
- Release builds pin
hatch-vcs(#55), publish only fromv*tags (#57), and do not expose OIDC credentials to pull-request benchmark code (#58). - Vendored libuv archives are checksum-verified (#63); a weekly signature-verifying workflow now tests new releases and opens update PRs (#71).
- CI now enforces
zig fmtand a checksum-pinned ZLint safety ruleset alongside Ruff and strict mypy (#72).