diff options
Diffstat (limited to 'llvm/lib/Support/Unix/Program.inc')
-rw-r--r-- | llvm/lib/Support/Unix/Program.inc | 180 |
1 files changed, 95 insertions, 85 deletions
diff --git a/llvm/lib/Support/Unix/Program.inc b/llvm/lib/Support/Unix/Program.inc index 089342030b97..897e22711ae2 100644 --- a/llvm/lib/Support/Unix/Program.inc +++ b/llvm/lib/Support/Unix/Program.inc @@ -1,4 +1,4 @@ -//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// +//===- llvm/Support/Unix/Program.inc ----------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic UNIX code that -//=== is guaranteed to work on *all* UNIX variants. +//=== WARNING: Implementation here must contain only generic UNIX +//=== code that is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// #include "llvm/Support/Program.h" @@ -55,7 +55,7 @@ #endif #if !USE_NSGETENVIRON - extern char **environ; +extern char **environ; #else #include <crt_externs.h> // _NSGetEnviron #endif @@ -89,12 +89,12 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name, SmallString<128> FilePath(Path); sys::path::append(FilePath, Name); if (sys::fs::can_execute(FilePath.c_str())) - return std::string(FilePath.str()); // Found the executable! + return std::string(FilePath.str()); // Found the executable! } return errc::no_such_file_or_directory; } -static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { +static bool RedirectIO(std::optional<StringRef> Path, int FD, std::string *ErrMsg) { if (!Path) // Noop return false; std::string File; @@ -105,10 +105,10 @@ static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { File = std::string(*Path); // Open the file - int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666); if (InFD == -1) { - MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " - + (FD == 0 ? "input" : "output")); + MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " + + (FD == 0 ? "input" : "output")); return true; } @@ -118,7 +118,7 @@ static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { close(InFD); return true; } - close(InFD); // Close the original FD + close(InFD); // Close the original FD return false; } @@ -135,30 +135,28 @@ static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg, File = Path->c_str(); if (int Err = posix_spawn_file_actions_addopen( - FileActions, FD, File, - FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) + FileActions, FD, File, FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) return MakeErrMsg(ErrMsg, "Cannot posix_spawn_file_actions_addopen", Err); return false; } #endif -static void TimeOutHandler(int Sig) { -} +static void TimeOutHandler(int Sig) {} static void SetMemoryLimits(unsigned size) { #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT struct rlimit r; - __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; + __typeof__(r.rlim_cur) limit = (__typeof__(r.rlim_cur))(size)*1048576; // Heap size - getrlimit (RLIMIT_DATA, &r); + getrlimit(RLIMIT_DATA, &r); r.rlim_cur = limit; - setrlimit (RLIMIT_DATA, &r); + setrlimit(RLIMIT_DATA, &r); #ifdef RLIMIT_RSS // Resident set size. - getrlimit (RLIMIT_RSS, &r); + getrlimit(RLIMIT_RSS, &r); r.rlim_cur = limit; - setrlimit (RLIMIT_RSS, &r); + setrlimit(RLIMIT_RSS, &r); #endif #endif } @@ -173,8 +171,8 @@ toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) { } static bool Execute(ProcessInfo &PI, StringRef Program, - ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env, - ArrayRef<Optional<StringRef>> Redirects, + ArrayRef<StringRef> Args, std::optional<ArrayRef<StringRef>> Env, + ArrayRef<std::optional<StringRef>> Redirects, unsigned MemoryLimit, std::string *ErrMsg, BitVector *AffinityMask) { if (!llvm::sys::fs::exists(Program)) { @@ -263,7 +261,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, posix_spawn_file_actions_destroy(FileActions); if (Err) - return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); + return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); PI.Pid = PID; PI.Process = PID; @@ -275,56 +273,62 @@ static bool Execute(ProcessInfo &PI, StringRef Program, // Create a child process. int child = fork(); switch (child) { - // An error occurred: Return to the caller. - case -1: - MakeErrMsg(ErrMsg, "Couldn't fork"); - return false; + // An error occurred: Return to the caller. + case -1: + MakeErrMsg(ErrMsg, "Couldn't fork"); + return false; - // Child process: Execute the program. - case 0: { - // Redirect file descriptors... - if (!Redirects.empty()) { - // Redirect stdin - if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; } - // Redirect stdout - if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; } - if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) { - // If stdout and stderr should go to the same place, redirect stderr - // to the FD already open for stdout. - if (-1 == dup2(1,2)) { - MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); - return false; - } - } else { - // Just redirect stderr - if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; } - } + // Child process: Execute the program. + case 0: { + // Redirect file descriptors... + if (!Redirects.empty()) { + // Redirect stdin + if (RedirectIO(Redirects[0], 0, ErrMsg)) { + return false; } - - // Set memory limits - if (MemoryLimit!=0) { - SetMemoryLimits(MemoryLimit); + // Redirect stdout + if (RedirectIO(Redirects[1], 1, ErrMsg)) { + return false; + } + if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) { + // If stdout and stderr should go to the same place, redirect stderr + // to the FD already open for stdout. + if (-1 == dup2(1, 2)) { + MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); + return false; + } + } else { + // Just redirect stderr + if (RedirectIO(Redirects[2], 2, ErrMsg)) { + return false; + } } + } - // Execute! - std::string PathStr = std::string(Program); - if (Envp != nullptr) - execve(PathStr.c_str(), const_cast<char **>(Argv), - const_cast<char **>(Envp)); - else - execv(PathStr.c_str(), const_cast<char **>(Argv)); - // If the execve() failed, we should exit. Follow Unix protocol and - // return 127 if the executable was not found, and 126 otherwise. - // Use _exit rather than exit so that atexit functions and static - // object destructors cloned from the parent process aren't - // redundantly run, and so that any data buffered in stdio buffers - // cloned from the parent aren't redundantly written out. - _exit(errno == ENOENT ? 127 : 126); + // Set memory limits + if (MemoryLimit != 0) { + SetMemoryLimits(MemoryLimit); } - // Parent process: Break out of the switch to do our processing. - default: - break; + // Execute! + std::string PathStr = std::string(Program); + if (Envp != nullptr) + execve(PathStr.c_str(), const_cast<char **>(Argv), + const_cast<char **>(Envp)); + else + execv(PathStr.c_str(), const_cast<char **>(Argv)); + // If the execve() failed, we should exit. Follow Unix protocol and + // return 127 if the executable was not found, and 126 otherwise. + // Use _exit rather than exit so that atexit functions and static + // object destructors cloned from the parent process aren't + // redundantly run, and so that any data buffered in stdio buffers + // cloned from the parent aren't redundantly written out. + _exit(errno == ENOENT ? 127 : 126); + } + + // Parent process: Break out of the switch to do our processing. + default: + break; } PI.Pid = child; @@ -339,7 +343,7 @@ namespace sys { #ifndef _AIX using ::wait4; #else -static pid_t (wait4)(pid_t pid, int *status, int options, struct rusage *usage); +static pid_t(wait4)(pid_t pid, int *status, int options, struct rusage *usage); #endif } // namespace sys @@ -347,11 +351,11 @@ static pid_t (wait4)(pid_t pid, int *status, int options, struct rusage *usage); #ifdef _AIX #ifndef _ALL_SOURCE -extern "C" pid_t (wait4)(pid_t pid, int *status, int options, - struct rusage *usage); +extern "C" pid_t(wait4)(pid_t pid, int *status, int options, + struct rusage *usage); #endif -pid_t (llvm::sys::wait4)(pid_t pid, int *status, int options, - struct rusage *usage) { +pid_t(llvm::sys::wait4)(pid_t pid, int *status, int options, + struct rusage *usage) { assert(pid > 0 && "Only expecting to handle actual PID values!"); assert((options & ~WNOHANG) == 0 && "Expecting WNOHANG at most!"); assert(usage && "Expecting usage collection!"); @@ -379,17 +383,23 @@ pid_t (llvm::sys::wait4)(pid_t pid, int *status, int options, } #endif -ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, - bool WaitUntilTerminates, std::string *ErrMsg, - Optional<ProcessStatistics> *ProcStat) { +ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, + std::optional<unsigned> SecondsToWait, + std::string *ErrMsg, + std::optional<ProcessStatistics> *ProcStat, + bool Polling) { struct sigaction Act, Old; assert(PI.Pid && "invalid pid to wait on, process not started?"); int WaitPidOptions = 0; pid_t ChildPid = PI.Pid; - if (WaitUntilTerminates) { - SecondsToWait = 0; - } else if (SecondsToWait) { + bool WaitUntilTerminates = false; + if (!SecondsToWait) { + WaitUntilTerminates = true; + } else { + if (*SecondsToWait == 0) + WaitPidOptions = WNOHANG; + // Install a timeout handler. The handler itself does nothing, but the // simple fact of having a handler at all causes the wait below to return // with EINTR, unlike if we used SIG_IGN. @@ -398,12 +408,11 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, sigemptyset(&Act.sa_mask); sigaction(SIGALRM, &Act, &Old); // FIXME The alarm signal may be delivered to another thread. - alarm(SecondsToWait); - } else if (SecondsToWait == 0) - WaitPidOptions = WNOHANG; + alarm(*SecondsToWait); + } // Parent process: Wait for the child process to terminate. - int status; + int status = 0; ProcessInfo WaitResult; rusage Info; if (ProcStat) @@ -418,7 +427,7 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, // Non-blocking wait. return WaitResult; } else { - if (SecondsToWait && errno == EINTR) { + if (SecondsToWait && errno == EINTR && !Polling) { // Kill the child. kill(PI.Pid, SIGKILL); @@ -494,13 +503,13 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, return WaitResult; } -std::error_code llvm::sys::ChangeStdinMode(fs::OpenFlags Flags){ +std::error_code llvm::sys::ChangeStdinMode(fs::OpenFlags Flags) { if (!(Flags & fs::OF_Text)) return ChangeStdinToBinary(); return std::error_code(); } -std::error_code llvm::sys::ChangeStdoutMode(fs::OpenFlags Flags){ +std::error_code llvm::sys::ChangeStdoutMode(fs::OpenFlags Flags) { if (!(Flags & fs::OF_Text)) return ChangeStdoutToBinary(); return std::error_code(); @@ -520,7 +529,8 @@ std::error_code llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, WindowsEncodingMethod Encoding /*unused*/) { std::error_code EC; - llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::OF_TextWithCRLF); + llvm::raw_fd_ostream OS(FileName, EC, + llvm::sys::fs::OpenFlags::OF_TextWithCRLF); if (EC) return EC; |