[WIP] Reading I/O from processes is uninterruptible, leading to hangs #109
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In some Linux environments and on FreeBSD, I've observed frequent hangs due to Swift Concurrency task cancellation terminating a process via the teardown sequence, while reading the output hangs forever. I expect the present issues on GitHub Actions Linux CI are due to this as well, though strangely I haven't been able to reproduce it on my local aarch64 Linux VM.
I'm not sure why this doesn't seem to occur on macOS and Windows, though a likely explanation is that Subprocess's Windows implementation doesn't use DispatchIO, and Dispatch is very buggy on non-Apple platforms.
I/O reading needs to be cancellable so that the library doesn't hang. This is quite readily reproducible with testCancelProcessVeryEarlyOnStressTest on FreeBSD; sleep will get zombied from the cancellation but the library will sit waiting for output forever if it managed to get into DispatchIO.read before the cancellation took effect.
To solve this, (ab)use an AsyncStream to force early cancellation when the parent task is cancelled.
Closes #108