Skip to content

Commit 16df512

Browse files
authored
Merge pull request #2382 from gmittert/ItWasMyGrandfathers
Fix Pipe Inheritance on Windows
2 parents 73dc1cf + 42f9f6b commit 16df512

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

Foundation/FileHandle.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,9 +979,12 @@ open class Pipe: NSObject {
979979

980980
public override init() {
981981
#if os(Windows)
982+
var saAttr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES(nLength: DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size), lpSecurityDescriptor: nil, bInheritHandle: true)
983+
982984
var hReadPipe: HANDLE?
983985
var hWritePipe: HANDLE?
984-
if !CreatePipe(&hReadPipe, &hWritePipe, nil, 0) {
986+
987+
if !CreatePipe(&hReadPipe, &hWritePipe, &saAttr, 0) {
985988
fatalError("CreatePipe failed")
986989
}
987990
self.fileHandleForReading = FileHandle(handle: hReadPipe!,

Foundation/Process.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,16 +386,30 @@ open class Process: NSObject {
386386

387387
var siStartupInfo: STARTUPINFOW = STARTUPINFOW()
388388
siStartupInfo.cb = DWORD(MemoryLayout<STARTUPINFOW>.size)
389+
siStartupInfo.dwFlags = DWORD(STARTF_USESTDHANDLES)
389390

390391
var _devNull: FileHandle?
391392
func devNullFd() throws -> HANDLE {
392393
_devNull = try _devNull ?? FileHandle(forUpdating: URL(fileURLWithPath: "NUL", isDirectory: false))
393394
return _devNull!.handle
394395
}
395396

397+
var modifiedPipes: [(handle: HANDLE, prevValue: DWORD)] = []
398+
defer { modifiedPipes.forEach { SetHandleInformation($0.handle, DWORD(HANDLE_FLAG_INHERIT), $0.prevValue) } }
399+
400+
func deferReset(handle: HANDLE) throws {
401+
var handleInfo: DWORD = 0
402+
guard GetHandleInformation(handle, &handleInfo) else {
403+
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
404+
}
405+
modifiedPipes.append((handle: handle, prevValue: handleInfo & DWORD(HANDLE_FLAG_INHERIT)))
406+
}
407+
396408
switch standardInput {
397409
case let pipe as Pipe:
398410
siStartupInfo.hStdInput = pipe.fileHandleForReading.handle
411+
try deferReset(handle: pipe.fileHandleForWriting.handle)
412+
SetHandleInformation(pipe.fileHandleForWriting.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
399413

400414
// nil or NullDevice maps to NUL
401415
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
@@ -404,12 +418,16 @@ open class Process: NSObject {
404418

405419
case let handle as FileHandle:
406420
siStartupInfo.hStdInput = handle.handle
421+
try deferReset(handle: handle.handle)
422+
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
407423
default: break
408424
}
409425

410426
switch standardOutput {
411427
case let pipe as Pipe:
412428
siStartupInfo.hStdOutput = pipe.fileHandleForWriting.handle
429+
try deferReset(handle: pipe.fileHandleForReading.handle)
430+
SetHandleInformation(pipe.fileHandleForReading.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
413431

414432
// nil or NullDevice maps to NUL
415433
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
@@ -418,12 +436,16 @@ open class Process: NSObject {
418436

419437
case let handle as FileHandle:
420438
siStartupInfo.hStdOutput = handle.handle
439+
try deferReset(handle: handle.handle)
440+
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
421441
default: break
422442
}
423443

424444
switch standardError {
425445
case let pipe as Pipe:
426446
siStartupInfo.hStdError = pipe.fileHandleForWriting.handle
447+
try deferReset(handle: pipe.fileHandleForReading.handle)
448+
SetHandleInformation(pipe.fileHandleForReading.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
427449

428450
// nil or NullDevice maps to NUL
429451
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
@@ -432,6 +454,8 @@ open class Process: NSObject {
432454

433455
case let handle as FileHandle:
434456
siStartupInfo.hStdError = handle.handle
457+
try deferReset(handle: handle.handle)
458+
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
435459
default: break
436460
}
437461

0 commit comments

Comments
 (0)