You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The API only allows collecting stdout and stderr separately, not as a single stream. This makes it impossible to build something like a Terminal app where the stdout+stderr of a process should be interleaved in the order of emission.
Ditto to @FranzBusch 's answer. The current design uses AsyncSequence specifically so you can utilize the rest of async-algorithm for things like this. @jakepetroules can you elaborate what's the issue you are seeing with merge?
@jakepetroules is right that the ordering with merge is not guaranteed to be the same as the subprocess that produced it since it is up to the executors scheduling. If we want to achieve the same ordering as the subprocess then we need to pass probably the same FD to as stdout and stderr and then offer a single async sequence for it.
Actually, this approach works with the current API surface:
let(readEnd, writeEnd)=tryFileDescriptor.pipe()
return tryawait readEnd.closeAfter{
// Direct both stdout and stderr to the same fd. Only set `closeAfterSpawningProcess` on one of the outputs so it isn't double-closed (similarly avoid using closeAfter for the same reason).
letresult=tryawaitSubprocess.run(.path(FilePath(url.filePath.str)),
arguments:.init(arguments),
environment: environment.map{.custom(.init($0))}??.inherit,
workingDirectory:(currentDirectoryURL?.filePath.str).map{FilePath($0)}??nil,
output:.fileDescriptor(writeEnd, closeAfterSpawningProcess:true),
error:.fileDescriptor(writeEnd, closeAfterSpawningProcess:false))
// read from `readEnd` here...
}
Actually I'll leave this open to allow consideration of a higher level API for this (which I think would be a reasonable addition). That said, there is a workaround for now, it's just a little lower level than I'd prefer, especially since the client has to provide their own mechanism to read from the fd in an async-friendly manner.
changed the title [-]There doesn't seem to be a way to collect merged stdout+stderr[/-][+]There should be dedicated API to collect merged stdout+stderr as a single stream (stdout and stderr going to the same underlying fd)[/+]on Jun 6, 2025
There should be dedicated API to collect merged stdout+stderr as a single stream (stdout and stderr going to the same underlying fd) · Issue #59 · swiftlang/swift-subprocess
Activity
FranzBusch commentedon Jun 4, 2025
Can't you use the
merge
algorithm ofswift-async-algorithms
to achieve this?jakepetroules commentedon Jun 4, 2025
How could that possibly produce the same result w.r.t. ordering?
iCharlesHu commentedon Jun 5, 2025
Ditto to @FranzBusch 's answer. The current design uses
AsyncSequence
specifically so you can utilize the rest ofasync-algorithm
for things like this. @jakepetroules can you elaborate what's the issue you are seeing withmerge
?FranzBusch commentedon Jun 6, 2025
@jakepetroules is right that the ordering with
merge
is not guaranteed to be the same as the subprocess that produced it since it is up to the executors scheduling. If we want to achieve the same ordering as the subprocess then we need to pass probably the same FD to as stdout and stderr and then offer a single async sequence for it.jakepetroules commentedon Jun 6, 2025
Actually, this approach works with the current API surface:
jakepetroules commentedon Jun 6, 2025
Actually I'll leave this open to allow consideration of a higher level API for this (which I think would be a reasonable addition). That said, there is a workaround for now, it's just a little lower level than I'd prefer, especially since the client has to provide their own mechanism to read from the fd in an async-friendly manner.
[-]There doesn't seem to be a way to collect merged stdout+stderr[/-][+]There should be dedicated API to collect merged stdout+stderr as a single stream (stdout and stderr going to the same underlying fd)[/+]