Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that rust's std sets MSG_NOSIGNAL for send(2) on illumos #148

Closed
sunshowers opened this issue Apr 3, 2024 · 2 comments
Closed

Ensure that rust's std sets MSG_NOSIGNAL for send(2) on illumos #148

sunshowers opened this issue Apr 3, 2024 · 2 comments
Assignees

Comments

@sunshowers
Copy link
Contributor

sunshowers commented Apr 3, 2024

(This is a general rust stdlib + illumos issue, filing here for tracking.)

tl;dr: rustc doesn't pass in MSG_NOSIGNAL on illumos -- we should fix that.


On Unix systems, by default, writing to a pipe that is broken causes two things to happen:

  1. A SIGPIPE signal is raised.
  2. An EPIPE error is returned.

The default disposition of SIGPIPE is to terminate the program. This is why things like ls | head terminate cleanly. But Rust sets the SIGPIPE disposition to SIG_IGN by default. There's a long history behind this: see rust-lang/rust#62569 for more.

The upshot of this is that Rust binaries fail with errors like:

BRM42220014 # /opt/oxide/oxlog/oxlog logs --archived oxz_switch | head -n1
/pool/ext/0c4ef358-5533-43db-ad38-a8eff716e53a/crypt/debug/oxz_switch/oxide-dendrite:default.log.1693451383
thread 'main' panicked at library/std/src/io/stdio.rs:1021:9:
failed printing to stdout: Broken pipe (os error 32)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

What we can do, from the perspective of shipping binaries written in Rust, is to simply set SIGPIPE to SIG_DFL for them. But there is a wrinkle: the same logic about broken pipes applies not just to writes to local pipes, but also network connections. While sending data, if there's a connection reset for some reason, SIGPIPE will be raised as well.

The good news is that many modern Unix platforms recognize this fundamental mismatch between what CLI tools want and what network services should do. They address it in one of two ways:

  1. Support a flag to send(2) called MSG_NOSIGNAL (Linux, several BSDs, and illumos).
  2. At socket creation time, set a flag called SO_NOSIGPIPE (Apple platforms, example use).

Focusing on 1 since that's what's relevant to illumos, I spent some time looking at the rustc source code, and saw that rustc does pass in MSG_NOSIGNAL where supported. However, the conditional doesn't include illumos, and so this flag isn't passed in on illumos even though it is supported.

Overall, this means that for a tool like oxlog, setting SIGPIPE to SIG_DFL is fine to do because it doesn't make any network requests (oxidecomputer/omicron#5358 does so). But other CLI tools like wicket, omdb and oxdb do make network requests -- and just exiting if a connection reset happens wouldn't be great.


It would be good to get this fixed in Rust upstream. There are likely tests for this behavior too, which we should ensure are enabled on illumos.

@sunshowers sunshowers changed the title Ensure that rustc sets MSG_NOSIGNAL for send(2) on illumos Ensure that rust's std sets MSG_NOSIGNAL for send(2) on illumos Apr 3, 2024
@sunshowers sunshowers self-assigned this Jul 27, 2024
@sunshowers
Copy link
Contributor Author

Addressed by rust-lang/rust#128259.

@sunshowers
Copy link
Contributor Author

rust-lang/rust#128259 has landed -- expected to be part of Rust 1.82.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant