Skip to content

Commit bfafdeb

Browse files
authored
Add a function on LocalFileOutputByteStream to disable SIGPIPE when writing data to it after the receiving end is closed (#502)
Without this, if we launch a subprocess and try to write data to its stdin after it has finished (or crashed), we would take down the current process due to the SIGPIPE, which is usually not desirable. Eg. SourceKit-LSP doesn’t want to exit with a SIGPIPE exit code if a launched swift-format subprocesses crashes before the file to format could transferred to its stdin. This mirrors behavior of `DispatchIO`, which also doesn’t emit a `SIGPIPE` when trying to write data to a stream whose receiving end has closed.
1 parent 418707b commit bfafdeb

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

Sources/TSCBasic/WritableByteStream.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,25 @@ public final class LocalFileOutputByteStream: FileOutputByteStream {
817817
throw error
818818
}
819819
}
820+
821+
#if canImport(Darwin)
822+
/// Disable the SIGPIPE if data is written to this stream after its receiving end has been terminated.
823+
///
824+
/// This can be useful to stop the current process from crashing if it tries to write data to the stdin stream of a
825+
/// subprocess after it has finished or crashed.
826+
///
827+
/// Only available on Darwin because `F_SETNOSIGPIPE` is not universally available.
828+
public func disableSigpipe() throws {
829+
let fileDescriptor = fileno(filePointer)
830+
if fileDescriptor == -1 {
831+
throw FileSystemError(.ioError(code: errno))
832+
}
833+
let fcntlResult = fcntl(fileDescriptor, F_SETNOSIGPIPE, 1)
834+
if fcntlResult == -1 {
835+
throw FileSystemError(.ioError(code: errno))
836+
}
837+
}
838+
#endif
820839
}
821840

822841
/// Public stdout stream instance.

0 commit comments

Comments
 (0)