Skip to content

Commit 630c3e0

Browse files
committed
Additional crash fixes when consuming process output
1 parent 3b33964 commit 630c3e0

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

Sources/SWBUtil/Process.swift

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -116,36 +116,39 @@ extension Process {
116116
let stderrData = try await stderrStream.collect()
117117
return (stdoutData: stdoutData, stderrData: stderrData)
118118
}
119-
120119
return Processes.ExecutionResult(exitStatus: exitStatus, stdout: Data(output.stdoutData), stderr: Data(output.stderrData))
121120
}
122121
}
123122

124123
public static func getMergedOutput(url: URL, arguments: [String], currentDirectoryURL: URL? = nil, environment: Environment? = nil, interruptible: Bool = true) async throws -> (exitStatus: Processes.ExitStatus, output: Data) {
125124
if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
126-
// Extend the lifetime of the pipe to avoid file descriptors being closed until the AsyncStream is finished being consumed.
127-
return try await withExtendedLifetime(Pipe()) { pipe in
128-
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
129-
process.standardOutputPipe = pipe
130-
process.standardErrorPipe = pipe
131-
return pipe.fileHandleForReading.bytes()
132-
} collect: { stream in
133-
try await stream.collect()
134-
}
135-
return (exitStatus: exitStatus, output: Data(output))
125+
let pipe = Pipe()
126+
127+
// Extend the lifetime of the pipes to avoid file descriptors being closed until the AsyncStream is finished being consumed.
128+
defer { withExtendedLifetime(pipe) {} }
129+
130+
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
131+
process.standardOutputPipe = pipe
132+
process.standardErrorPipe = pipe
133+
return pipe.fileHandleForReading.bytes()
134+
} collect: { stream in
135+
try await stream.collect()
136136
}
137+
return (exitStatus: exitStatus, output: Data(output))
137138
} else {
138-
// Extend the lifetime of the pipe to avoid file descriptors being closed until the AsyncStream is finished being consumed.
139-
return try await withExtendedLifetime(Pipe()) { pipe in
140-
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
141-
process.standardOutputPipe = pipe
142-
process.standardErrorPipe = pipe
143-
return pipe.fileHandleForReading._bytes()
144-
} collect: { stream in
145-
try await stream.collect()
146-
}
147-
return (exitStatus: exitStatus, output: Data(output))
139+
let pipe = Pipe()
140+
141+
// Extend the lifetime of the pipes to avoid file descriptors being closed until the AsyncStream is finished being consumed.
142+
defer { withExtendedLifetime(pipe) {} }
143+
144+
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
145+
process.standardOutputPipe = pipe
146+
process.standardErrorPipe = pipe
147+
return pipe.fileHandleForReading._bytes()
148+
} collect: { stream in
149+
try await stream.collect()
148150
}
151+
return (exitStatus: exitStatus, output: Data(output))
149152
}
150153
}
151154

0 commit comments

Comments
 (0)