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)")
|
throw RecordingError.unknown("无法启动 ffmpeg: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待完成
|
// 异步等待进程完成(不阻塞 cooperative thread)
|
||||||
proc.waitUntilExit()
|
await waitForProcess(proc)
|
||||||
stderrPipe.fileHandleForReading.readabilityHandler = nil
|
stderrPipe.fileHandleForReading.readabilityHandler = nil
|
||||||
isRecording = false
|
isRecording = false
|
||||||
|
|
||||||
@ -136,6 +136,22 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
|||||||
|
|
||||||
// MARK: - Private
|
// 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 {
|
private func findFFmpeg() -> String {
|
||||||
let paths = [
|
let paths = [
|
||||||
"/opt/homebrew/bin/ffmpeg",
|
"/opt/homebrew/bin/ffmpeg",
|
||||||
@ -186,7 +202,7 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
try proc.run()
|
try proc.run()
|
||||||
proc.waitUntilExit()
|
await waitForProcess(proc)
|
||||||
} catch {
|
} catch {
|
||||||
throw RecordingError.unknown("无法分析输出文件")
|
throw RecordingError.unknown("无法分析输出文件")
|
||||||
}
|
}
|
||||||
@ -269,7 +285,7 @@ public final class FFmpegRecorder: StreamRecorderEngine {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
try proc.run()
|
try proc.run()
|
||||||
proc.waitUntilExit()
|
await waitForProcess(proc)
|
||||||
} catch {
|
} catch {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user