diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -14,6 +14,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "llvm/Support/Errno.h" +#include "llvm/Support/FileSystem.h" #include #include @@ -143,9 +144,32 @@ // Close everything besides stdin, stdout, and stderr that has no file // action to avoid leaking. Only do this when debugging, as elsewhere we // actually rely on passing open descriptors to child processes. - for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) - if (!info.GetFileActionForFD(fd) && fd != error_fd) - close(fd); + + std::string proc_fd_path = "/proc/self/fd"; + std::error_code EC; + bool result; + EC = llvm::sys::fs::is_directory(proc_fd_path, result); + if (result) { + std::vector files_to_close; + // Directory iterator doesn't ensure any sequence. + for (llvm::sys::fs::directory_iterator iter(proc_fd_path, EC), FileEnd; + iter != FileEnd && !EC; iter.increment(EC)) { + int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1)); + + // Don't close first three entries since they are + // stdin/stdout/stderr + if ((fd > 2) && !info.GetFileActionForFD(fd) && fd != error_fd) + files_to_close.push_back(fd); + } + for (auto &file_to_close : files_to_close) + close(file_to_close); + } else { + // /proc/self/fd didn't work - trying the slow way instead + for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) + if (!info.GetFileActionForFD(fd) && fd != error_fd) { + close(fd); + } + } // Start tracing this child that is about to exec. if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)