Resolve native macOS stdout-capture regressions on both architectures
- Dominant language
- Rust
- Stars
- 53
- Forks
- 16
- Avg merge
- 4h 22m
- Merged PRs (30d)
- 46
Description
Observed at PR #631 head `d811e0c2accc8997eecb5071f8752f88e9fb44e4`. [Failing CI job](https://github.com/wavefnd/Wave/actions/runs/34737095086/job/103670349676).
Both native macOS jobs fail the same two tests in `tools.test_std_io_runtime`:
- `test_capture_has_no_inherited_pipe_reader_and_no_parent_leak`: fixture exits 12.
- `test_capture_writer_observes_consumer_closure`: fixture exits 11.
`capture.wave` exit 12 combines child exit status, byte count and payload checks. `capture_close.wave` exit 11 combines wait failure and non-normal child termination. Logs contain no child status or payload, so they do not establish a leaked reader, exec failure, or SIGPIPE root cause.
Reproduce on each native host with the repository std installed:
```sh
cargo test --locked --test std_io_regressions --jobs 2 -- --nocapture
```
Trace fork return conventions, descriptor remapping/closure, script execution and child wait status. Compare a minimal executable child with the generated Python shebang child to distinguish runtime defects from fixture assumptions. Retain the closed-standard-descriptor and early-consumer-closure checks.
Acceptance:
- Both capture scenarios pass repeatedly on native amd64 and arm64 macOS.
- A missing child reader is demonstrated by descriptor inspection and bounded producer termination.
- Preserve child status and capture contents when a check fails.
- No libc binding workaround and no platform skip to hide failure.
Follow-up to #559 after its child-reader cleanup; related to broader Darwin provider audit #434. The two failures are intentionally grouped until evidence establishes different root causes.
Source references:
- [tests/fixtures/io/capture.wave](https://github.com/wavefnd/Wave/blob/d811e0c2accc8997eecb5071f8752f88e9fb44e4/tests/fixtures/io/capture.wave)
- [tests/fixtures/io/capture_close.wave](https://github.com/wavefnd/Wave/blob/d811e0c2accc8997eecb5071f8752f88e9fb44e4/tests/fixtures/io/capture_close.wave)
- [tools/test_std_io_runtime.py](https://github.com/wavefnd/Wave/blob/d811e0c2accc8997eecb5071f8752f88e9fb44e4/tools/test_std_io_runtime.py)
- [std/process/spawn.wave](https://github.com/wavefnd/Wave/blob/d811e0c2accc8997eecb5071f8752f88e9fb44e4/std/process/spawn.wave)
Both affected jobs: [amd64](https://github.com/wavefnd/Wave/actions/runs/34737095086/job/103670349659), [arm64](https://github.com/wavefnd/Wave/actions/runs/34737095086/job/103670349676).
Contributor guide
Research direction
Run cargo test --locked --test std_io_regressions --jobs 2 -- --nocapture on native amd64 and arm64 macOS. Read tools/test_std_io_runtime.py, the capture.wave and capture_close.wave fixtures, and std/process/spawn.wave; trace fork returns, descriptor remapping and closure, script execution, and child wait status. Done means both scenarios pass repeatedly, with descriptor inspection and bounded producer termination demonstrating the missing-reader behavior while preserving child status and captured contents on failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- operating-systems, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100