5 ms·
Go, Rust, and Zig make it impossible to interrupt most blocking syscalls, because they automatically retry on EINTR. [1] Go supports timeouts on network & file
by networkimprov 6y ago
Go, Rust, and Zig make it impossible to interrupt most blocking syscalls, because they automatically retry on EINTR. [1]
Go supports timeouts on network & file read/write ops, which can be used to interrupt them.
[1] https://github.com/golang/go/issues/41054 https://github.com/golang/go/issues/41054
- Arnavion 6y ago>Go, Rust, and Zig make it impossible to interrupt most blocking syscalls, because they automatically retry on EINTR. This is not true of Rust. Some of the convenience wrappers (std::io::Read::read_exact, etc) on top of the basic primitives (std::io::Read::read, etc) do retry for you (and explicitly document it), but not "Rust" as a whole. The primitives map one-to-one to calls of read/write/sendto/recvfrom and bubble up ErrorKind::Interrupted to the caller just fine.
- networkimprov 6y agoThe Rust filesystem API works (or once did) as I described. This can render an application unusable when trying a network filesystem or storage device that's unavailable. https://github.com/rust-lang/rust/issues/11214 https://github.com/rust-lang/rust/issues/11214 To support user intervention when a task takes longer than expected, all blocking syscalls should be interruptible.
- Arnavion 6y agoLinking to discussions from pre-1.0 does not help your assertion. std::fs::File's impl of std::io::Read: https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/fs.rs#L610-L612 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... -> https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/sys/unix/fs.rs#L778-L780 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... -> https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/sys/unix/fd.rs#L68-L73 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... Again, as I said, it corresponds one-to-one with a call to the underlying read API. The retries for ErrorKind::Interrupted are done by higher abstractions like std::io::Read::read_exact, and they explicitly document that they do this. https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/io/mod.rs#L775 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f...
- networkimprov 6y agoApologies if I got this wrong, but you've linked read(), and I'm referring to mkdir() et al. Have they taken out the EINTR retries which were added for the issue I linked?
- Arnavion 6y agostd::fs::create_dir: https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/fs.rs#L1876-L1878 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... -> https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/fs.rs#L2158-L2161 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... -> https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/fs.rs#L2163-L2165 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f... -> https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11fac204921b9ad8a0c5a3/library/std/src/sys/unix/fs.rs#L851-L855 https://github.com/rust-lang/rust/blob/7fc048f0712ba515ca11f...
- deleted 6y ago[deleted]
- cyphar 6y agoGo only recently started handling -EINTR correctly (retrying the operation) though I do agree that this should've only been done in the higher-level wrappers. The "os" package shouldn't be doing retries IMHO. Pre-1.14 -EINTRs were quite rare in "normal" Go programs so the stdlib basically ignored them, but 1.14 introduced preemption which resulted in many more -EINTRs and quite a few Go programs were broken as a result. So in many ways this behaviour was necessary to un-break backwards compatibility. If Go had made the interruption semantics -- which had existed for at least a decade before Go came about -- clearer from the outset then maybe this whole business could've been avoided. This is symptomatic of the reasons why container runtimes (at least, those written in Go) have historically been vary wary of Go updates. Several years ago, each Go release would change some minor semantics of the Go runtime and cause breakages...