fix: replace blocking waitUntilExit() with async continuation
proc.waitUntilExit() blocks cooperative thread pool threads and deadlocks in Swift Concurrency Task context because NSRunLoop notifications aren't processed. Replace with terminationHandler + withCheckedContinuation pattern.
This commit is contained in:
parent
68806e1190
commit
acb232d38b
@ -106,8 +106,8 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
||||
throw RecordingError.unknown("无法启动 ffmpeg: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
// 等待完成
|
||||
proc.waitUntilExit()
|
||||
// 异步等待进程完成(不阻塞 cooperative thread)
|
||||
await waitForProcess(proc)
|
||||
stderrPipe.fileHandleForReading.readabilityHandler = nil
|
||||
isRecording = false
|
||||
|
||||
@ -136,6 +136,22 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
/// Async-friendly process wait — uses terminationHandler + continuation
|
||||
/// instead of blocking waitUntilExit() which deadlocks in Task context
|
||||
private func waitForProcess(_ proc: Process) async {
|
||||
guard proc.isRunning else { return }
|
||||
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
|
||||
proc.terminationHandler = { _ in
|
||||
continuation.resume()
|
||||
}
|
||||
// Race condition: process may have exited between isRunning check and setting handler
|
||||
if !proc.isRunning {
|
||||
proc.terminationHandler = nil
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func findFFmpeg() -> String {
|
||||
let paths = [
|
||||
"/opt/homebrew/bin/ffmpeg",
|
||||
@ -186,7 +202,7 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
||||
|
||||
do {
|
||||
try proc.run()
|
||||
proc.waitUntilExit()
|
||||
await waitForProcess(proc)
|
||||
} catch {
|
||||
throw RecordingError.unknown("无法分析输出文件")
|
||||
}
|
||||
@ -269,7 +285,7 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
||||
|
||||
do {
|
||||
try proc.run()
|
||||
proc.waitUntilExit()
|
||||
await waitForProcess(proc)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user