Skip to content

Commit f3632c1

Browse files
committed
Process: handle a possible case of a nil runloop source
If the process terminates before the runloop source being woken up, we could end up with the callout from CoreFoundation where the `process.runLoopSource` returns a `nil`, breaking an invariant for the `CFRunLoopSourceInvalidate`. This would then cascade into a null pointer dereference when trying to invalidate a non-existent runloop source. Guard against such a case by ensuring that we have a source before invalidation. We additionally assert that if we do not have a runloop source, the process has finished execution as we always expect to have a runloop source while the process is running. The runloop source is created when the process is launched, so it is not possible for the process to not have started before the runloop is awoken.
1 parent efedfc3 commit f3632c1

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

Sources/Foundation/Process.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,8 +649,16 @@ open class Process: NSObject {
649649

650650
process.isRunning = false
651651

652-
// Invalidate the source and wake up the run loop, if it is available
653-
CFRunLoopSourceInvalidate(process.runLoopSource)
652+
// Invalidate the source and wake up the run loop, if it is
653+
// available. The runloop source may no longer be available if the
654+
// process has exited. Failure to verify that we have a runloop
655+
// source breaks an invariant that `null` not be passed to the
656+
// function.
657+
if let source = process.runLoopSource {
658+
CFRunLoopSourceInvalidate(source)
659+
} else {
660+
assert(process.hasFinished)
661+
}
654662
if let runloop = process.runLoop {
655663
CFRunLoopWakeUp(runloop._cfRunLoop)
656664
}

0 commit comments

Comments
 (0)