refactor(macos): centralize process pipe draining
This commit is contained in:
@@ -278,10 +278,7 @@ enum GatewayEnvironment {
|
||||
process.standardOutput = pipe
|
||||
process.standardError = pipe
|
||||
do {
|
||||
try process.run()
|
||||
// Read pipe before waitUntilExit to avoid potential deadlock
|
||||
let data = pipe.fileHandleForReading.readToEndSafely()
|
||||
process.waitUntilExit()
|
||||
let data = try process.runAndReadToEnd(from: pipe)
|
||||
let elapsedMs = Int(Date().timeIntervalSince(start) * 1000)
|
||||
if elapsedMs > 500 {
|
||||
self.logger.warning(
|
||||
|
||||
@@ -72,11 +72,11 @@ enum LaunchAgentManager {
|
||||
let process = Process()
|
||||
process.launchPath = "/bin/launchctl"
|
||||
process.arguments = args
|
||||
process.standardOutput = Pipe()
|
||||
process.standardError = Pipe()
|
||||
let pipe = Pipe()
|
||||
process.standardOutput = pipe
|
||||
process.standardError = pipe
|
||||
do {
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
_ = try process.runAndReadToEnd(from: pipe)
|
||||
return process.terminationStatus
|
||||
} catch {
|
||||
return -1
|
||||
|
||||
@@ -16,12 +16,7 @@ enum Launchctl {
|
||||
process.standardOutput = pipe
|
||||
process.standardError = pipe
|
||||
do {
|
||||
try process.run()
|
||||
// Read pipe output BEFORE waitUntilExit to avoid deadlock.
|
||||
// If the process writes enough to fill the pipe buffer (~64KB),
|
||||
// it will block until someone reads. Reading first prevents this.
|
||||
let data = pipe.fileHandleForReading.readToEndSafely()
|
||||
process.waitUntilExit()
|
||||
let data = try process.runAndReadToEnd(from: pipe)
|
||||
let output = String(data: data, encoding: .utf8) ?? ""
|
||||
return Result(status: process.terminationStatus, output: output)
|
||||
} catch {
|
||||
|
||||
@@ -580,11 +580,10 @@ final class NodePairingApprovalPrompter {
|
||||
process.standardError = pipe
|
||||
|
||||
do {
|
||||
try process.run()
|
||||
_ = try process.runAndReadToEnd(from: pipe)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
process.waitUntilExit()
|
||||
return process.terminationStatus == 0
|
||||
}.value
|
||||
}
|
||||
|
||||
@@ -203,10 +203,7 @@ actor PortGuardian {
|
||||
proc.standardOutput = pipe
|
||||
proc.standardError = Pipe()
|
||||
do {
|
||||
try proc.run()
|
||||
// Read pipe before waitUntilExit to avoid potential deadlock
|
||||
let data = pipe.fileHandleForReading.readToEndSafely()
|
||||
proc.waitUntilExit()
|
||||
let data = try proc.runAndReadToEnd(from: pipe)
|
||||
guard !data.isEmpty else { return nil }
|
||||
return String(data: data, encoding: .utf8)?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
11
apps/macos/Sources/Clawdbot/Process+PipeRead.swift
Normal file
11
apps/macos/Sources/Clawdbot/Process+PipeRead.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
extension Process {
|
||||
/// Runs the process and drains the given pipe before waiting to avoid blocking on full buffers.
|
||||
func runAndReadToEnd(from pipe: Pipe) throws -> Data {
|
||||
try self.run()
|
||||
let data = pipe.fileHandleForReading.readToEndSafely()
|
||||
self.waitUntilExit()
|
||||
return data
|
||||
}
|
||||
}
|
||||
@@ -133,10 +133,7 @@ enum RuntimeLocator {
|
||||
process.standardError = pipe
|
||||
|
||||
do {
|
||||
try process.run()
|
||||
// Read pipe before waitUntilExit to avoid potential deadlock
|
||||
let data = pipe.fileHandleForReading.readToEndSafely()
|
||||
process.waitUntilExit()
|
||||
let data = try process.runAndReadToEnd(from: pipe)
|
||||
let elapsedMs = Int(Date().timeIntervalSince(start) * 1000)
|
||||
if elapsedMs > 500 {
|
||||
self.logger.warning(
|
||||
|
||||
Reference in New Issue
Block a user