-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
sort: use uucore SIGPIPE handling for broken pipes #10264
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
base: main
Are you sure you want to change the base?
Conversation
|
I'm a bit hesitant that sort should add the error type checks on every write, its not entirely clear how to do this but I think there should be a consistent pattern that we can abstract and use for all of the utilities. Edit: After more investigating, this is all handled by the SIGPIPE flags internally and thats how GNU handles all of this too |
|
Another thing to note is that the error code for GNU that gets returned is 141 |
CodSpeed Performance ReportMerging this PR will degrade performance by 3.19%Comparing Summary
Performance Changes
Footnotes
|
|
This unfortunately is a very complex area and very opaque to someone new to the project but the behaviour is actually handled by the SIGPIPE flags and we can replicate all of this logic by just having: This handles all of the logic that you are adding there and also handles if the SIGPIPE is ignore to match GNU, it also matches those correct error codes. This would also require adding the signals feature to the cargo.toml for sort |
|
So that approach does fix all of the issues except for one, when there's an IOFailure with sort GNU has an error code of 2, this is a pre-existing issue unrelated to the goal of fixing the broken pipes but should be made into a new issue. In this exact test scenario it only shows up with the SIGPIPE is ignored |
|
@ChrisDryden I’m trying to add a regression test for the pipeline case ( #[test]
#[cfg(unix)]
fn test_broken_pipe_default_exit_code_141() {
let mut cmd = new_ucmd!();
let mut child = cmd.args(&["ext_sort.txt"]).run_no_wait();
// Simulate downstream closing early (like `| head -n 0`).
child.close_stdout();
// No diagnostic should be printed.
child.wait().unwrap().no_stderr().code_is(141);
}Is there a recommended way in uutests to simulate “downstream closes pipe early” so the child actually hits SIGPIPE/EPIPE? (e.g. a helper to close the read end, or a pattern other utils use.) Happy to align the test to whatever pattern other utilities use (I couldn’t find one beyond the existing |
|
Theres really not any good macros that I can find for this type of behaviour, this is how it was tested similarly in the seq utility: I would add comments as a TODO in the test that say that when the signal is trapped that the error code is returning as a 1 instead of a 2, I think that would be outside of the scope of this PR and this would already such a big improvement already |
Enable uucore SIGPIPE capture + conditional pipe error handling so `sort | head -n 0` does not emit "Broken pipe" diagnostics and matches GNU exit status behavior. Add a shell-pipeline regression test that asserts no stderr and exit code 141 when the downstream closes early. Also apply small idiomatic cleanups (e.g. `.map(Into::into)`).
|
Thanks, that makes sense. I’ll push these changes shortly 😊 |
|
the current failure: |
|
I think it's because the test is being run under |
|
GNU testsuite comparison: |
efc36f8 to
b9b61f8
Compare
|
CI target doesn’t have |
|
GNU testsuite comparison: |
Closes #10260
When sort's stdout is closed early (e.g.
sort | head -n 0), writing returns EPIPE. GNU sort treats this as success, but uutils sort printed a "write failed: Broken pipe" diagnostic and exited with an error.Problem
Running:
produced:
sort: write failed: 'standard output': Broken pipeGNU sort exits silently and successfully instead.
Solution
init_sigpipe_capture+ conditionalenable_pipe_errors)Tests