Skip to content

Commit 9e38d01

Browse files
authored
Merge pull request #20 from jakepetroules/fix-windows-pipe
Restore the pipe() function removed in #17
2 parents 55a8427 + c91164d commit 9e38d01

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

Sources/Subprocess/Configuration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ internal struct CreatedPipe {
871871
}
872872

873873
internal init(closeWhenDone: Bool) throws {
874-
let pipe = try FileDescriptor.pipe()
874+
let pipe = try FileDescriptor.ssp_pipe()
875875

876876
self.readFileDescriptor = .init(
877877
pipe.readEnd,

Sources/Subprocess/Platforms/Subprocess+Windows.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,46 @@ internal typealias PlatformFileDescriptor = HANDLE
976976

977977
// MARK: - Pipe Support
978978
extension FileDescriptor {
979+
// NOTE: Not the same as SwiftSystem's FileDescriptor.pipe, which has different behavior,
980+
// because it passes _O_NOINHERIT through the _pipe interface (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/pipe),
981+
// which ends up setting bInheritHandle to false in the SECURITY_ATTRIBUTES (see ucrt/conio/pipe.cpp in the ucrt sources).
982+
internal static func ssp_pipe() throws -> (
983+
readEnd: FileDescriptor,
984+
writeEnd: FileDescriptor
985+
) {
986+
var saAttributes: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES()
987+
saAttributes.nLength = DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size)
988+
saAttributes.bInheritHandle = true
989+
saAttributes.lpSecurityDescriptor = nil
990+
991+
var readHandle: HANDLE? = nil
992+
var writeHandle: HANDLE? = nil
993+
guard CreatePipe(&readHandle, &writeHandle, &saAttributes, 0),
994+
readHandle != INVALID_HANDLE_VALUE,
995+
writeHandle != INVALID_HANDLE_VALUE,
996+
let readHandle: HANDLE = readHandle,
997+
let writeHandle: HANDLE = writeHandle
998+
else {
999+
throw SubprocessError(
1000+
code: .init(.failedToCreatePipe),
1001+
underlyingError: .init(rawValue: GetLastError())
1002+
)
1003+
}
1004+
let readFd = _open_osfhandle(
1005+
intptr_t(bitPattern: readHandle),
1006+
FileDescriptor.AccessMode.readOnly.rawValue
1007+
)
1008+
let writeFd = _open_osfhandle(
1009+
intptr_t(bitPattern: writeHandle),
1010+
FileDescriptor.AccessMode.writeOnly.rawValue
1011+
)
1012+
1013+
return (
1014+
readEnd: FileDescriptor(rawValue: readFd),
1015+
writeEnd: FileDescriptor(rawValue: writeFd)
1016+
)
1017+
}
1018+
9791019
var platformDescriptor: PlatformFileDescriptor {
9801020
return HANDLE(bitPattern: _get_osfhandle(self.rawValue))!
9811021
}

Tests/SubprocessTests/SubprocessTests+Windows.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ extension SubprocessWindowsTests {
762762
@available(SubprocessSpan, *)
763763
#endif
764764
@Test func testRunDetached() async throws {
765-
let (readFd, writeFd) = try FileDescriptor.pipe()
765+
let (readFd, writeFd) = try FileDescriptor.ssp_pipe()
766766
SetHandleInformation(
767767
readFd.platformDescriptor,
768768
DWORD(HANDLE_FLAG_INHERIT),

0 commit comments

Comments
 (0)