Skip to content

Commit cc6f746

Browse files
authored
Merge pull request #728 from rconnell9/rconnell/async-crash-62
[6.2.0] Fix crash when running swift test for swift-build
2 parents a1f29aa + a82bf52 commit cc6f746

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

‎Sources/SWBUtil/Process.swift‎

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

115123
publicstaticfunc getMergedOutput(url:URL, arguments:[String], currentDirectoryURL:URL?=nil, environment:Environment?=nil, interruptible:Bool=true)asyncthrows->(exitStatus:Processes.ExitStatus, output:Data){
116124
if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2,*){
117-
// Extend the lifetime of the pipe to avoid file descriptors being closed until the AsyncStream is finished being consumed.
118-
returntryawaitwithExtendedLifetime(Pipe()){ pipe in
119-
let(exitStatus, output)=tryawait_getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible){ process in
120-
process.standardOutputPipe = pipe
121-
process.standardErrorPipe = pipe
122-
return pipe.fileHandleForReading.bytes(on:.global())
123-
} collect:{ stream in
124-
tryawait stream.collect()
125-
}
126-
return(exitStatus: exitStatus, output:Data(output))
125+
letpipe=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)=tryawait_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(on:.global())
134+
} collect:{ stream in
135+
tryawait stream.collect()
127136
}
137+
return(exitStatus: exitStatus, output:Data(output))
128138
}else{
129-
// Extend the lifetime of the pipe to avoid file descriptors being closed until the AsyncStream is finished being consumed.
130-
returntryawaitwithExtendedLifetime(Pipe()){ pipe in
131-
let(exitStatus, output)=tryawait_getOutput(url: url, arguments: arguments, currentDirectoryURL: currentDirectoryURL, environment: environment, interruptible: interruptible){ process in
132-
process.standardOutputPipe = pipe
133-
process.standardErrorPipe = pipe
134-
return pipe.fileHandleForReading._bytes(on:.global())
135-
} collect:{ stream in
136-
tryawait stream.collect()
137-
}
138-
return(exitStatus: exitStatus, output:Data(output))
139+
letpipe=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)=tryawait_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(on:.global())
148+
} collect:{ stream in
149+
tryawait stream.collect()
139150
}
151+
return(exitStatus: exitStatus, output:Data(output))
140152
}
141153
}
142154

0 commit comments

Comments
(0)