Skip to content

Commit 53cfb81

Browse files
fischman-bcnyMaxDesiatov
authored andcommitted
waitUntilExit: ignore RunLoop.run()'s return value (#4740)
* 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. * 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 (cherry picked from commit 818de48)
1 parent c078b15 commit 53cfb81

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

CoreFoundation/Base.subproj/CFRuntime.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ void __CFInitialize(void) {
11791179
if (!__CFInitialized && !__CFInitializing) {
11801180
__CFInitializing = 1;
11811181

1182-
#if __HAS_DISPATCH__
1182+
#if __HAS_DISPATCH__ && !TARGET_OS_MAC
11831183
// libdispatch has to be initialized before CoreFoundation, so to avoid
11841184
// issues with static initializer ordering, we are doing it explicitly.
11851185
libdispatch_init();

Sources/Foundation/Process.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,14 +1134,17 @@ open class Process: NSObject {
11341134
open func waitUntilExit() {
11351135
let runInterval = 0.05
11361136
let currentRunLoop = RunLoop.current
1137-
let checkRunLoop : () -> Bool = (currentRunLoop == self.runLoop)
1138-
? { currentRunLoop.run(mode: .default, before: Date(timeIntervalSinceNow: runInterval)) }
1139-
: { currentRunLoop.run(until: Date(timeIntervalSinceNow: runInterval)); return true }
11401137

1141-
// update .runLoop to allow early wakeup.
1138+
let runRunLoop : () -> Void = (currentRunLoop == self.runLoop)
1139+
? { currentRunLoop.run(mode: .default, before: Date(timeIntervalSinceNow: runInterval)) }
1140+
: { currentRunLoop.run(until: Date(timeIntervalSinceNow: runInterval)) }
1141+
// update .runLoop to allow early wakeup triggered by terminateRunLoop.
11421142
self.runLoop = currentRunLoop
1143-
while self.isRunning && checkRunLoop() {}
1144-
1143+
1144+
while self.isRunning {
1145+
runRunLoop()
1146+
}
1147+
11451148
self.runLoop = nil
11461149
self.runLoopSource = nil
11471150
}

0 commit comments

Comments
 (0)