@@ -1223,17 +1223,59 @@ fn test_sigpipe_panic() {
12231223// but uutils currently returns 1 in that mode.
12241224#[ test]
12251225#[ cfg( unix) ]
1226- fn test_broken_pipe_exits_141_no_stderr ( ) {
1226+ fn test_broken_pipe_exits_sigpipe_no_stderr ( ) {
1227+ use std:: io:: { BufRead , BufReader , Write } ;
1228+ use std:: os:: unix:: process:: ExitStatusExt ;
1229+ use std:: process:: { Command , Stdio } ;
1230+
12271231 let scene = TestScenario :: new ( util_name ! ( ) ) ;
1228- let bin = scene. bin_path . clone ( ) . into_os_string ( ) ;
1229- scene
1230- . cmd ( "bash" )
1231- . arg ( "-c" )
1232- . arg ( r#"{ seq 1 10000 | "$BIN" sort -n 2>err | head -n1; }; echo ${PIPESTATUS[1]} >code"# )
1233- . env ( "BIN" , & bin)
1234- . succeeds ( ) ;
1235- assert ! ( scene. fixtures. read( "err" ) . is_empty( ) ) ;
1236- assert_eq ! ( scene. fixtures. read( "code" ) . trim( ) , "141" ) ;
1232+ let bin = scene. bin_path . clone ( ) ;
1233+
1234+ // Run multicall: coreutils sort -n
1235+ let mut child = Command :: new ( bin)
1236+ . arg ( "sort" )
1237+ . arg ( "-n" )
1238+ . stdin ( Stdio :: piped ( ) )
1239+ . stdout ( Stdio :: piped ( ) )
1240+ . stderr ( Stdio :: piped ( ) )
1241+ . spawn ( )
1242+ . expect ( "spawn sort" ) ;
1243+
1244+ // Feed enough input that sort will try to write output.
1245+ {
1246+ let mut stdin = child. stdin . take ( ) . expect ( "take stdin" ) ;
1247+ for i in 1 ..=10000 {
1248+ writeln ! ( stdin, "{i}" ) . expect ( "write stdin" ) ;
1249+ }
1250+ // drop(stdin) closes stdin
1251+ }
1252+
1253+ // Read a single output line, then close stdout to trigger SIGPIPE on the child
1254+ // the next time it writes (like `| head -n1`).
1255+ {
1256+ let stdout = child. stdout . take ( ) . expect ( "take stdout" ) ;
1257+ let mut r = BufReader :: new ( stdout) ;
1258+ let mut line = String :: new ( ) ;
1259+ let _ = r. read_line ( & mut line) . expect ( "read first line" ) ;
1260+ // drop(r) closes the read end
1261+ }
1262+
1263+ let output = child. wait_with_output ( ) . expect ( "wait" ) ;
1264+
1265+ // No "Broken pipe" diagnostic.
1266+ assert ! (
1267+ output. stderr. is_empty( ) ,
1268+ "expected empty stderr, got: {:?}" ,
1269+ String :: from_utf8_lossy( & output. stderr)
1270+ ) ;
1271+
1272+ // Shells report SIGPIPE as 128+13=141, but Rust exposes it as a signal.
1273+ assert_eq ! (
1274+ output. status. signal( ) ,
1275+ Some ( libc:: SIGPIPE ) ,
1276+ "expected SIGPIPE; status={:?}" ,
1277+ output. status
1278+ ) ;
12371279}
12381280
12391281#[ test]
0 commit comments