@@ -976,6 +976,46 @@ internal typealias PlatformFileDescriptor = HANDLE
976976
977977// MARK: - Pipe Support
978978extension 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 }
0 commit comments