3 ms·
Handling SIGINT (ctrl-c) with child processes is tricky, but a more pervasive problem for Rust CLI programs is handling SIGPIPE. For historical reasons the comp
by mprovost 1y ago
Handling SIGINT (ctrl-c) with child processes is tricky, but a more pervasive problem for Rust CLI programs is handling SIGPIPE. For historical reasons the compiler adds a signal handler before calling main() which ignores SIGPIPE. It means when you pipe your Rust CLI program's output to something like head, instead of being killed by the signal sent when head closes the pipe, you get a write error and usually print an error message instead of silently dying. You can match on the type of write error and skip printing a message when it's from a broken pipe, but a more subtle problem is that the shell sets the exit status of a program killed by a signal to 128 + the signal number, so 141 in the case of a broken pipe. You can emulate this behaviour by checking for a broken pipe and explicitly exiting with a 141 status code, but it's not possible to fully reproduce being killed by a signal. There's been an issue to make this configurable (the latest proposal is via a compiler flag) for years.
- aidenn0 1y agoThat's good to know; ysh[1] will treat pipelines with a SIGPIPE indicative exit code as successful to allow e.g. foo |head -n2 to be treated as successful. I haven't seen anyone complaining yet about rust programs breaking this idiom, but I'll keep an eye out for it. 1: https://oils.pub/release/latest/doc/ysh-tour.html https://oils.pub/release/latest/doc/ysh-tour.html
- mprovost 1y agoIn other shells, the status of the pipeline is the exit status of the last process, so in this case that would be head which exits with 0.