From f4eb86bae6460636cef1bb96c68515047ca67435 Mon Sep 17 00:00:00 2001 From: Johannes Weiss Date: Thu, 22 Aug 2019 19:44:11 +0100 Subject: [PATCH 1/3] do not inherit fds --- Foundation/Process.swift | 18 ++++++++++++++++++ TestFoundation/TestProcess.swift | 20 ++++++++++++++++++++ TestFoundation/xdgTestHelper/main.swift | 14 +++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Foundation/Process.swift b/Foundation/Process.swift index c89a244a92..1881cd5c89 100644 --- a/Foundation/Process.swift +++ b/Foundation/Process.swift @@ -8,6 +8,7 @@ // import CoreFoundation +import Darwin extension Process { public enum TerminationReason : Int { @@ -837,6 +838,16 @@ open class Process: NSObject { posix(_CFPosixSpawnFileActionsAddClose(fileActions, fd)) } + #if os(macOS) + var spawnAttrs: posix_spawnattr_t? = nil + posix_spawnattr_init(&spawnAttrs) + posix_spawnattr_setflags(&spawnAttrs, .init(POSIX_SPAWN_CLOEXEC_DEFAULT)) + #else + for fd in 3.. () throws -> Void)] { var tests = [ @@ -592,6 +611,7 @@ class TestProcess : XCTestCase { ("test_redirect_all_using_null", test_redirect_all_using_null), ("test_redirect_all_using_nil", test_redirect_all_using_nil), ("test_plutil", test_plutil), + ("test_fileDescriptorsAreNotInherited", test_fileDescriptorsAreNotInherited), ] #if !os(Windows) diff --git a/TestFoundation/xdgTestHelper/main.swift b/TestFoundation/xdgTestHelper/main.swift index 1950db2750..c010892d83 100644 --- a/TestFoundation/xdgTestHelper/main.swift +++ b/TestFoundation/xdgTestHelper/main.swift @@ -206,6 +206,15 @@ func cat(_ args: ArraySlice.Iterator) { exit(exitCode) } +func printOpenFileDescriptors() { + for fd in 0.. Date: Thu, 22 Aug 2019 14:04:23 -0700 Subject: [PATCH 2/3] Cleanup: - POSIX_SPAWN_CLOEXEC_DEFAULT is a constant offered by the Darwin module. Import it conditionally that way. - Do not close Pipe/FileHandle-owned fds. --- Foundation/Process.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Foundation/Process.swift b/Foundation/Process.swift index 1881cd5c89..6dd06f1079 100644 --- a/Foundation/Process.swift +++ b/Foundation/Process.swift @@ -8,7 +8,10 @@ // import CoreFoundation + +#if canImport(Darwin) import Darwin +#endif extension Process { public enum TerminationReason : Int { @@ -838,12 +841,16 @@ open class Process: NSObject { posix(_CFPosixSpawnFileActionsAddClose(fileActions, fd)) } - #if os(macOS) + #if canImport(Darwin) var spawnAttrs: posix_spawnattr_t? = nil posix_spawnattr_init(&spawnAttrs) posix_spawnattr_setflags(&spawnAttrs, .init(POSIX_SPAWN_CLOEXEC_DEFAULT)) #else - for fd in 3.. Date: Fri, 30 Aug 2019 15:21:12 +0100 Subject: [PATCH 3/3] more cleanup --- Foundation/Process.swift | 3 ++- TestFoundation/TestProcess.swift | 19 +++++++++++++------ TestFoundation/xdgTestHelper/main.swift | 4 +++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Foundation/Process.swift b/Foundation/Process.swift index 6dd06f1079..6c0e30e1ce 100644 --- a/Foundation/Process.swift +++ b/Foundation/Process.swift @@ -848,7 +848,8 @@ open class Process: NSObject { #else for fd in 3 ..< getdtablesize() { guard adddup2[fd] == nil && - !addclose.contains(fd) else { + !addclose.contains(fd) && + fd != taskSocketPair[1] else { continue // Do not double-close descriptors, or close those pertaining to Pipes or FileHandles we want inherited. } posix(_CFPosixSpawnFileActionsAddClose(fileActions, fd)) diff --git a/TestFoundation/TestProcess.swift b/TestFoundation/TestProcess.swift index f23371c511..3f6ccae85a 100644 --- a/TestFoundation/TestProcess.swift +++ b/TestFoundation/TestProcess.swift @@ -567,7 +567,7 @@ class TestProcess : XCTestCase { func test_fileDescriptorsAreNotInherited() throws { let task = Process() - let clonedFD = dup(1) + let someExtraFDs = [dup(1), dup(1), dup(1), dup(1), dup(1), dup(1), dup(1)] task.executableURL = xdgTestHelperURL() task.arguments = ["--print-open-file-descriptors"] task.standardInput = FileHandle.nullDevice @@ -576,13 +576,20 @@ class TestProcess : XCTestCase { task.standardError = FileHandle.nullDevice XCTAssertNoThrow(try task.run()) - try task.run() try stdoutPipe.fileHandleForWriting.close() let stdoutData = try stdoutPipe.fileHandleForReading.readToEnd() task.waitUntilExit() - print(String(decoding: stdoutData ?? Data(), as: Unicode.UTF8.self)) - XCTAssertEqual("0\n1\n2\n", String(decoding: stdoutData ?? Data(), as: Unicode.UTF8.self)) - close(clonedFD) + let stdoutString = String(decoding: stdoutData ?? Data(), as: Unicode.UTF8.self) + #if os(macOS) + XCTAssertEqual("0\n1\n2\n", stdoutString) + #else + // on Linux we should also have a /dev/urandom open as well as some socket that Process uses for something. + XCTAssert(stdoutString.utf8.starts(with: "0\n1\n2\n3\n".utf8)) + XCTAssertEqual(stdoutString.components(separatedBy: "\n").count, 6, "\(stdoutString)") + #endif + for fd in someExtraFDs { + close(fd) + } } static var allTests: [(String, (TestProcess) -> () throws -> Void)] { @@ -611,7 +618,6 @@ class TestProcess : XCTestCase { ("test_redirect_all_using_null", test_redirect_all_using_null), ("test_redirect_all_using_nil", test_redirect_all_using_nil), ("test_plutil", test_plutil), - ("test_fileDescriptorsAreNotInherited", test_fileDescriptorsAreNotInherited), ] #if !os(Windows) @@ -619,6 +625,7 @@ class TestProcess : XCTestCase { tests += [ ("test_interrupt", test_interrupt), ("test_suspend_resume", test_suspend_resume), + ("test_fileDescriptorsAreNotInherited", test_fileDescriptorsAreNotInherited), ] #endif return tests diff --git a/TestFoundation/xdgTestHelper/main.swift b/TestFoundation/xdgTestHelper/main.swift index c010892d83..3f4e115ce3 100644 --- a/TestFoundation/xdgTestHelper/main.swift +++ b/TestFoundation/xdgTestHelper/main.swift @@ -206,6 +206,7 @@ func cat(_ args: ArraySlice.Iterator) { exit(exitCode) } +#if !os(Windows) func printOpenFileDescriptors() { for fd in 0..