Skip to content

Commit 69776aa

Browse files
authored
Merge pull request #24521 from drodriguez/android-stop-leaking-fds
[android] Stop leaking FDs in parent test process.
2 parents 84565dd + 7d0b78d commit 69776aa

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ public func spawnChild(_ args: [String])
217217
if pid == 0 {
218218
// pid of 0 means we are now in the child process.
219219
// Capture the output before executing the program.
220+
close(childStdout.readFD)
221+
close(childStdin.writeFD)
222+
close(childStderr.readFD)
223+
close(childToParentPipe.readFD)
220224
dup2(childStdout.writeFD, STDOUT_FILENO)
221225
dup2(childStdin.readFD, STDIN_FILENO)
222226
dup2(childStderr.writeFD, STDERR_FILENO)
@@ -261,6 +265,41 @@ public func spawnChild(_ args: [String])
261265

262266
// Close the pipe when we're done writing the error.
263267
close(childToParentPipe.writeFD)
268+
} else {
269+
close(childToParentPipe.writeFD)
270+
271+
// Figure out if the child’s call to execve was successful or not.
272+
var readfds = _stdlib_fd_set()
273+
readfds.set(childToParentPipe.readFD)
274+
var writefds = _stdlib_fd_set()
275+
var errorfds = _stdlib_fd_set()
276+
errorfds.set(childToParentPipe.readFD)
277+
278+
var ret: CInt
279+
repeat {
280+
ret = _stdlib_select(&readfds, &writefds, &errorfds, nil)
281+
} while ret == -1 && errno == EINTR
282+
if ret <= 0 {
283+
fatalError("select() returned an error: \(errno)")
284+
}
285+
286+
if readfds.isset(childToParentPipe.readFD) || errorfds.isset(childToParentPipe.readFD) {
287+
var childErrno: CInt = 0
288+
let readResult: ssize_t = withUnsafeMutablePointer(to: &childErrno) {
289+
return read(childToParentPipe.readFD, $0, MemoryLayout.size(ofValue: $0.pointee))
290+
}
291+
if readResult == 0 {
292+
// We read an EOF indicating that the child's call to execve was successful.
293+
} else if readResult < 0 {
294+
fatalError("read() returned error: \(errno)")
295+
} else {
296+
// We read an error from the child.
297+
print(String(cString: strerror(childErrno)))
298+
preconditionFailure("execve() failed")
299+
}
300+
}
301+
302+
close(childToParentPipe.readFD)
264303
}
265304
#else
266305
var fileActions = _make_posix_spawn_file_actions_t()

0 commit comments

Comments
 (0)