From 1501fe09343455cc8da9e8a2112cf98b04efb868 Mon Sep 17 00:00:00 2001 From: Ami Fischman Date: Fri, 5 May 2023 15:11:13 -0700 Subject: [PATCH 1/2] waitUntilExit: ignore RunLoop.run()'s return value We've been seeing frequent (but not reproducible in isolation) failures in our builds where waitUntilExit returns but terminationStatus fails its precondition on hasFinished because isRunning is still true. This is a speculative fix, since I haven't been able to reproduce the failure in a self-contained test. This should be safe since Process.waitUntilExit isn't spec'd to relate to RunLoop. In particular there is no guarantee that "stopping" a RunLoop should cause waitUntilExit to return before the monitored process has exited. --- Sources/Foundation/Process.swift | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Sources/Foundation/Process.swift b/Sources/Foundation/Process.swift index e064711296..542cc94cf1 100644 --- a/Sources/Foundation/Process.swift +++ b/Sources/Foundation/Process.swift @@ -1134,14 +1134,17 @@ open class Process: NSObject { open func waitUntilExit() { let runInterval = 0.05 let currentRunLoop = RunLoop.current - let checkRunLoop : () -> Bool = (currentRunLoop == self.runLoop) - ? { currentRunLoop.run(mode: .default, before: Date(timeIntervalSinceNow: runInterval)) } - : { currentRunLoop.run(until: Date(timeIntervalSinceNow: runInterval)); return true } - // update .runLoop to allow early wakeup. + let runRunLoop : () -> Void = (currentRunLoop == self.runLoop) + ? { currentRunLoop.run(mode: .default, before: Date(timeIntervalSinceNow: runInterval)) } + : { currentRunLoop.run(until: Date(timeIntervalSinceNow: runInterval)) } + // update .runLoop to allow early wakeup triggered by terminateRunLoop. self.runLoop = currentRunLoop - while self.isRunning && checkRunLoop() {} - + + while self.isRunning { + runRunLoop() + } + self.runLoop = nil self.runLoopSource = nil } From 5404e239d28e1ab32d7b58b5338980620cb5ea06 Mon Sep 17 00:00:00 2001 From: Ami Fischman Date: Thu, 18 May 2023 14:08:26 -0700 Subject: [PATCH 2/2] Exclude libdispatch_init() on TARGET_OS_MAC because it duplicates the call from the static constructor https://github.com/apple/swift-corelibs-libdispatch/blob/7fb9d5ceea562d60fe34ec55b6b165ae5aca38eb/src/init.c#L56 --- CoreFoundation/Base.subproj/CFRuntime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CoreFoundation/Base.subproj/CFRuntime.c b/CoreFoundation/Base.subproj/CFRuntime.c index 4aaa65ed3c..afdbf5d21e 100644 --- a/CoreFoundation/Base.subproj/CFRuntime.c +++ b/CoreFoundation/Base.subproj/CFRuntime.c @@ -1179,7 +1179,7 @@ void __CFInitialize(void) { if (!__CFInitialized && !__CFInitializing) { __CFInitializing = 1; -#if __HAS_DISPATCH__ +#if __HAS_DISPATCH__ && !TARGET_OS_MAC // libdispatch has to be initialized before CoreFoundation, so to avoid // issues with static initializer ordering, we are doing it explicitly. libdispatch_init();