Safe Rust, corrupt wire: memory safety is not cancellation safety

51 points vorjdux 23 comments

Wrote this after building Monocoque, a pure-Rust ZeroMQ runtime (ZMTP 3.1) on io_uring via compio.

The argument in short:

Rust's core idea is correctness by construction, and it applies that idea to exactly one thing: memory. Owned-buffer APIs like compio and tokio-uring make the io_uring buffer-ownership problem unrepresentable, which is genuinely great. But memory safety is not cancellation safety. A multipart write cancelled mid-frame, say a timeout dropping the future between frames, leaves every buffer valid and accounted for and the wire corrupt: half a message on the stream, the peer's parser desynced. The borrow checker is happy and the runtime is happy, because the bug lives one level up in protocol state, where neither of them is looking.

The post is about where "safe" stops (memory) and where it quietly becomes your job (protocol and state under cancellation), the structural fix I went with, and why cancellation-as-Drop, which grew out of the epoll readiness world, sits awkwardly with completion I/O and stateful protocols.

https://vorjdux.com/articles/safe-rust-corrupt-wire.html

My own blog. Happy to get into any of it in the comments.