Skip to content

Commit 3b33964

Browse files
committed
Alter usage of async withExtendedLifetime that is causing crash in swift concurrency
1 parent a2443f7 commit 3b33964

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

Sources/SWBUtil/Process.swift

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,33 +82,42 @@ extension Process {
8282
extension Process {
8383
public static func getOutput(url: URL, arguments: [String], currentDirectoryURL: URL? = nil, environment: Environment? = nil, interruptible: Bool = true) async throws -> Processes.ExecutionResult {
8484
if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
85+
let stdoutPipe = Pipe()
86+
let stderrPipe = Pipe()
87+
8588
// Extend the lifetime of the pipes to avoid file descriptors being closed until the AsyncStream is finished being consumed.
86-
return try await withExtendedLifetime((Pipe(), Pipe())) { (stdoutPipe, stderrPipe) in
87-
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
88-
let stdoutStream = process.makeStream(for: \.standardOutputPipe, using: stdoutPipe)
89-
let stderrStream = process.makeStream(for: \.standardErrorPipe, using: stderrPipe)
90-
return (stdoutStream, stderrStream)
91-
} collect: { (stdoutStream, stderrStream) in
92-
let stdoutData = try await stdoutStream.collect()
93-
let stderrData = try await stderrStream.collect()
94-
return (stdoutData: stdoutData, stderrData: stderrData)
95-
}
96-
return Processes.ExecutionResult(exitStatus: exitStatus, stdout: Data(output.stdoutData), stderr: Data(output.stderrData))
89+
defer { withExtendedLifetime(stdoutPipe) {} }
90+
defer { withExtendedLifetime(stderrPipe) {} }
91+
92+
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
93+
let stdoutStream = process.makeStream(for: \.standardOutputPipe, using: stdoutPipe)
94+
let stderrStream = process.makeStream(for: \.standardErrorPipe, using: stderrPipe)
95+
return (stdoutStream, stderrStream)
96+
} collect: { (stdoutStream, stderrStream) in
97+
let stdoutData = try await stdoutStream.collect()
98+
let stderrData = try await stderrStream.collect()
99+
return (stdoutData: stdoutData, stderrData: stderrData)
97100
}
101+
return Processes.ExecutionResult(exitStatus: exitStatus, stdout: Data(output.stdoutData), stderr: Data(output.stderrData))
98102
} else {
103+
let stdoutPipe = Pipe()
104+
let stderrPipe = Pipe()
105+
99106
// Extend the lifetime of the pipes to avoid file descriptors being closed until the AsyncStream is finished being consumed.
100-
return try await withExtendedLifetime((Pipe(), Pipe())) { (stdoutPipe, stderrPipe) in
101-
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
102-
let stdoutStream = process._makeStream(for: \.standardOutputPipe, using: stdoutPipe)
103-
let stderrStream = process._makeStream(for: \.standardErrorPipe, using: stderrPipe)
104-
return (stdoutStream, stderrStream)
105-
} collect: { (stdoutStream, stderrStream) in
106-
let stdoutData = try await stdoutStream.collect()
107-
let stderrData = try await stderrStream.collect()
108-
return (stdoutData: stdoutData, stderrData: stderrData)
109-
}
110-
return Processes.ExecutionResult(exitStatus: exitStatus, stdout: Data(output.stdoutData), stderr: Data(output.stderrData))
107+
defer { withExtendedLifetime(stdoutPipe) {} }
108+
defer { withExtendedLifetime(stderrPipe) {} }
109+
110+
let (exitStatus, output) = try await _getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible) { process in
111+
let stdoutStream = process._makeStream(for: \.standardOutputPipe, using: stdoutPipe)
112+
let stderrStream = process._makeStream(for: \.standardErrorPipe, using: stderrPipe)
113+
return (stdoutStream, stderrStream)
114+
} collect: { (stdoutStream, stderrStream) in
115+
let stdoutData = try await stdoutStream.collect()
116+
let stderrData = try await stderrStream.collect()
117+
return (stdoutData: stdoutData, stderrData: stderrData)
111118
}
119+
120+
return Processes.ExecutionResult(exitStatus: exitStatus, stdout: Data(output.stdoutData), stderr: Data(output.stderrData))
112121
}
113122
}
114123

0 commit comments

Comments
 (0)