fc24fa27
test: the reparented sleeper does not hold the pipe naming it
a73x 2026-09-03 19:13
Commit message
src/cli/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -2020,7 +2020,15 @@ test "waitPidGone: returns only once the OS has no such process" { | |||
| 2020 | // Use a grandchild because a direct child can remain as a zombie that signal | 2020 | // Use a grandchild because a direct child can remain as a zombie that signal |
| 2021 | // zero still finds. The shell exits after printing the sleeper pid, leaving | 2021 | // zero still finds. The shell exits after printing the sleeper pid, leaving |
| 2022 | // the reparented process to terminate independently. | 2022 | // the reparented process to terminate independently. |
| 2023 | var child = std.process.Child.init(&.{ "sh", "-c", "sleep 0.3 & echo $!" }, std.testing.allocator); | 2023 | // |
| 2024 | // The sleeper's stdio goes to /dev/null so it does not hold the pipe this | ||
| 2025 | // test reads the pid through. Inheriting it made the read below block for | ||
| 2026 | // the sleeper's whole lifetime, so the pid was already dying by the time | ||
| 2027 | // the aliveness check ran and the wait proved nothing — on macOS the check | ||
| 2028 | // lost that race outright and the test failed at its first line. A second | ||
| 2029 | // of life, spent while `waitPidGone` polls, is what makes the wait mean | ||
| 2030 | // something. | ||
| 2031 | var child = std.process.Child.init(&.{ "sh", "-c", "sleep 1 >/dev/null 2>&1 </dev/null & echo $!" }, std.testing.allocator); | ||
| 2024 | child.stdout_behavior = .Pipe; | 2032 | child.stdout_behavior = .Pipe; |
| 2025 | try child.spawn(); | 2033 | try child.spawn(); |
| 2026 | var buf: [32]u8 = undefined; | 2034 | var buf: [32]u8 = undefined; |