LCOV - code coverage report
Current view: top level - lib/Support/Unix - Program.inc (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 82 182 45.1 %
Date: 2018-10-20 13:21:21 Functions: 10 13 76.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file implements the Unix specific portion of the Program class.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : //===----------------------------------------------------------------------===//
      15             : //=== WARNING: Implementation here must contain only generic UNIX code that
      16             : //===          is guaranteed to work on *all* UNIX variants.
      17             : //===----------------------------------------------------------------------===//
      18             : 
      19             : #include "Unix.h"
      20             : #include "llvm/ADT/StringExtras.h"
      21             : #include "llvm/Config/config.h"
      22             : #include "llvm/Support/Compiler.h"
      23             : #include "llvm/Support/Errc.h"
      24             : #include "llvm/Support/FileSystem.h"
      25             : #include "llvm/Support/Path.h"
      26             : #include "llvm/Support/StringSaver.h"
      27             : #include "llvm/Support/raw_ostream.h"
      28             : #if HAVE_SYS_STAT_H
      29             : #include <sys/stat.h>
      30             : #endif
      31             : #if HAVE_SYS_RESOURCE_H
      32             : #include <sys/resource.h>
      33             : #endif
      34             : #if HAVE_SIGNAL_H
      35             : #include <signal.h>
      36             : #endif
      37             : #if HAVE_FCNTL_H
      38             : #include <fcntl.h>
      39             : #endif
      40             : #if HAVE_UNISTD_H
      41             : #include <unistd.h>
      42             : #endif
      43             : #ifdef HAVE_POSIX_SPAWN
      44             : #include <spawn.h>
      45             : 
      46             : #if defined(__APPLE__)
      47             : #include <TargetConditionals.h>
      48             : #endif
      49             : 
      50             : #if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
      51             : #define USE_NSGETENVIRON 1
      52             : #else
      53             : #define USE_NSGETENVIRON 0
      54             : #endif
      55             : 
      56             : #if !USE_NSGETENVIRON
      57             :   extern char **environ;
      58             : #else
      59             : #include <crt_externs.h> // _NSGetEnviron
      60             : #endif
      61             : #endif
      62             : 
      63             : namespace llvm {
      64             : 
      65             : using namespace sys;
      66             : 
      67     2898378 : ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
      68             : 
      69       50060 : ErrorOr<std::string> sys::findProgramByName(StringRef Name,
      70             :                                             ArrayRef<StringRef> Paths) {
      71             :   assert(!Name.empty() && "Must have a name!");
      72             :   // Use the given path verbatim if it contains any slashes; this matches
      73             :   // the behavior of sh(1) and friends.
      74       50060 :   if (Name.find('/') != StringRef::npos)
      75        4865 :     return std::string(Name);
      76             : 
      77             :   SmallVector<StringRef, 16> EnvironmentPaths;
      78       45195 :   if (Paths.empty())
      79       45194 :     if (const char *PathEnv = std::getenv("PATH")) {
      80       45190 :       SplitString(PathEnv, EnvironmentPaths, ":");
      81             :       Paths = EnvironmentPaths;
      82             :     }
      83             : 
      84      261243 :   for (auto Path : Paths) {
      85      225357 :     if (Path.empty())
      86           0 :       continue;
      87             : 
      88             :     // Check to see if this first directory contains the executable...
      89             :     SmallString<128> FilePath(Path);
      90      225357 :     sys::path::append(FilePath, Name);
      91      225357 :     if (sys::fs::can_execute(FilePath.c_str()))
      92        9309 :       return std::string(FilePath.str()); // Found the executable!
      93             :   }
      94             :   return errc::no_such_file_or_directory;
      95             : }
      96             : 
      97           0 : static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
      98           0 :   if (!Path) // Noop
      99             :     return false;
     100             :   std::string File;
     101           0 :   if (Path->empty())
     102             :     // Redirect empty paths to /dev/null
     103             :     File = "/dev/null";
     104             :   else
     105           0 :     File = *Path;
     106             : 
     107             :   // Open the file
     108           0 :   int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
     109           0 :   if (InFD == -1) {
     110           0 :     MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
     111           0 :               + (FD == 0 ? "input" : "output"));
     112           0 :     return true;
     113             :   }
     114             : 
     115             :   // Install it as the requested FD
     116           0 :   if (dup2(InFD, FD) == -1) {
     117           0 :     MakeErrMsg(ErrMsg, "Cannot dup2");
     118           0 :     close(InFD);
     119           0 :     return true;
     120             :   }
     121           0 :   close(InFD);      // Close the original FD
     122           0 :   return false;
     123             : }
     124             : 
     125             : #ifdef HAVE_POSIX_SPAWN
     126          48 : static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
     127             :                           posix_spawn_file_actions_t *FileActions) {
     128          48 :   if (!Path) // Noop
     129             :     return false;
     130             :   const char *File;
     131          31 :   if (Path->empty())
     132             :     // Redirect empty paths to /dev/null
     133             :     File = "/dev/null";
     134             :   else
     135             :     File = Path->c_str();
     136             : 
     137          56 :   if (int Err = posix_spawn_file_actions_addopen(
     138             :           FileActions, FD, File,
     139             :           FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
     140           0 :     return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
     141             :   return false;
     142             : }
     143             : #endif
     144             : 
     145           1 : static void TimeOutHandler(int Sig) {
     146           1 : }
     147             : 
     148           0 : static void SetMemoryLimits(unsigned size) {
     149             : #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
     150             :   struct rlimit r;
     151           0 :   __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
     152             : 
     153             :   // Heap size
     154           0 :   getrlimit (RLIMIT_DATA, &r);
     155           0 :   r.rlim_cur = limit;
     156           0 :   setrlimit (RLIMIT_DATA, &r);
     157             : #ifdef RLIMIT_RSS
     158             :   // Resident set size.
     159           0 :   getrlimit (RLIMIT_RSS, &r);
     160           0 :   r.rlim_cur = limit;
     161           0 :   setrlimit (RLIMIT_RSS, &r);
     162             : #endif
     163             : #endif
     164           0 : }
     165             : 
     166             : }
     167             : 
     168             : static std::vector<const char *>
     169       19307 : toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
     170             :   std::vector<const char *> Result;
     171      994323 :   for (StringRef S : Strings)
     172      975016 :     Result.push_back(Saver.save(S).data());
     173       19307 :   Result.push_back(nullptr);
     174       19307 :   return Result;
     175             : }
     176             : 
     177           0 : static bool Execute(ProcessInfo &PI, StringRef Program,
     178             :                     ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
     179             :                     ArrayRef<Optional<StringRef>> Redirects,
     180             :                     unsigned MemoryLimit, std::string *ErrMsg) {
     181           0 :   if (!llvm::sys::fs::exists(Program)) {
     182           0 :     if (ErrMsg)
     183           0 :       *ErrMsg = std::string("Executable \"") + Program.str() +
     184           0 :                 std::string("\" doesn't exist!");
     185           0 :     return false;
     186             :   }
     187             : 
     188           0 :   BumpPtrAllocator Allocator;
     189             :   StringSaver Saver(Allocator);
     190             :   std::vector<const char *> ArgVector, EnvVector;
     191             :   const char **Argv = nullptr;
     192             :   const char **Envp = nullptr;
     193           0 :   ArgVector = toNullTerminatedCStringArray(Args, Saver);
     194           0 :   Argv = ArgVector.data();
     195           0 :   if (Env) {
     196           0 :     EnvVector = toNullTerminatedCStringArray(*Env, Saver);
     197           0 :     Envp = EnvVector.data();
     198             :   }
     199             : 
     200             :   // If this OS has posix_spawn and there is no memory limit being implied, use
     201             :   // posix_spawn.  It is more efficient than fork/exec.
     202             : #ifdef HAVE_POSIX_SPAWN
     203           0 :   if (MemoryLimit == 0) {
     204             :     posix_spawn_file_actions_t FileActionsStore;
     205             :     posix_spawn_file_actions_t *FileActions = nullptr;
     206             : 
     207             :     // If we call posix_spawn_file_actions_addopen we have to make sure the
     208             :     // c strings we pass to it stay alive until the call to posix_spawn,
     209             :     // so we copy any StringRefs into this variable.
     210           0 :     std::string RedirectsStorage[3];
     211             : 
     212           0 :     if (!Redirects.empty()) {
     213             :       assert(Redirects.size() == 3);
     214           0 :       std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
     215           0 :       for (int I = 0; I < 3; ++I) {
     216           0 :         if (Redirects[I]) {
     217           0 :           RedirectsStorage[I] = *Redirects[I];
     218           0 :           RedirectsStr[I] = &RedirectsStorage[I];
     219             :         }
     220             :       }
     221             : 
     222             :       FileActions = &FileActionsStore;
     223           0 :       posix_spawn_file_actions_init(FileActions);
     224             : 
     225             :       // Redirect stdin/stdout.
     226           0 :       if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
     227           0 :           RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
     228           0 :         return false;
     229           0 :       if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
     230             :         // Just redirect stderr
     231           0 :         if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
     232           0 :           return false;
     233             :       } else {
     234             :         // If stdout and stderr should go to the same place, redirect stderr
     235             :         // to the FD already open for stdout.
     236           0 :         if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
     237           0 :           return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
     238             :       }
     239             :     }
     240             : 
     241           0 :     if (!Envp)
     242             : #if !USE_NSGETENVIRON
     243           0 :       Envp = const_cast<const char **>(environ);
     244             : #else
     245             :       // environ is missing in dylibs.
     246             :       Envp = const_cast<const char **>(*_NSGetEnviron());
     247             : #endif
     248             : 
     249             :     // Explicitly initialized to prevent what appears to be a valgrind false
     250             :     // positive.
     251           0 :     pid_t PID = 0;
     252           0 :     int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
     253             :                           /*attrp*/ nullptr, const_cast<char **>(Argv),
     254             :                           const_cast<char **>(Envp));
     255             : 
     256           0 :     if (FileActions)
     257           0 :       posix_spawn_file_actions_destroy(FileActions);
     258             : 
     259           0 :     if (Err)
     260           0 :      return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
     261             : 
     262           0 :     PI.Pid = PID;
     263           0 :     PI.Process = PID;
     264             : 
     265           0 :     return true;
     266             :   }
     267             : #endif
     268             : 
     269             :   // Create a child process.
     270           0 :   int child = fork();
     271           0 :   switch (child) {
     272             :     // An error occurred:  Return to the caller.
     273             :     case -1:
     274           0 :       MakeErrMsg(ErrMsg, "Couldn't fork");
     275           0 :       return false;
     276             : 
     277             :     // Child process: Execute the program.
     278           0 :     case 0: {
     279             :       // Redirect file descriptors...
     280           0 :       if (!Redirects.empty()) {
     281             :         // Redirect stdin
     282           0 :         if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
     283             :         // Redirect stdout
     284           0 :         if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
     285           0 :         if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
     286             :           // If stdout and stderr should go to the same place, redirect stderr
     287             :           // to the FD already open for stdout.
     288           0 :           if (-1 == dup2(1,2)) {
     289           0 :             MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
     290           0 :             return false;
     291             :           }
     292             :         } else {
     293             :           // Just redirect stderr
     294           0 :           if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
     295             :         }
     296             :       }
     297             : 
     298             :       // Set memory limits
     299             :       if (MemoryLimit!=0) {
     300           0 :         SetMemoryLimits(MemoryLimit);
     301             :       }
     302             : 
     303             :       // Execute!
     304             :       std::string PathStr = Program;
     305           0 :       if (Envp != nullptr)
     306           0 :         execve(PathStr.c_str(), const_cast<char **>(Argv),
     307             :                const_cast<char **>(Envp));
     308             :       else
     309           0 :         execv(PathStr.c_str(), const_cast<char **>(Argv));
     310             :       // If the execve() failed, we should exit. Follow Unix protocol and
     311             :       // return 127 if the executable was not found, and 126 otherwise.
     312             :       // Use _exit rather than exit so that atexit functions and static
     313             :       // object destructors cloned from the parent process aren't
     314             :       // redundantly run, and so that any data buffered in stdio buffers
     315             :       // cloned from the parent aren't redundantly written out.
     316           0 :       _exit(errno == ENOENT ? 127 : 126);
     317             :     }
     318             : 
     319             :     // Parent process: Break out of the switch to do our processing.
     320             :     default:
     321             :       break;
     322             :   }
     323             : 
     324           0 :   PI.Pid = child;
     325           0 :   PI.Process = child;
     326             : 
     327           0 :   return true;
     328             : }
     329             : 
     330             : namespace llvm {
     331             : 
     332     2879072 : ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
     333             :                       bool WaitUntilTerminates, std::string *ErrMsg) {
     334             :   struct sigaction Act, Old;
     335             :   assert(PI.Pid && "invalid pid to wait on, process not started?");
     336             : 
     337             :   int WaitPidOptions = 0;
     338     2879072 :   pid_t ChildPid = PI.Pid;
     339     2879072 :   if (WaitUntilTerminates) {
     340             :     SecondsToWait = 0;
     341     2859936 :   } else if (SecondsToWait) {
     342             :     // Install a timeout handler.  The handler itself does nothing, but the
     343             :     // simple fact of having a handler at all causes the wait below to return
     344             :     // with EINTR, unlike if we used SIG_IGN.
     345         166 :     memset(&Act, 0, sizeof(Act));
     346         166 :     Act.sa_handler = TimeOutHandler;
     347         166 :     sigemptyset(&Act.sa_mask);
     348         166 :     sigaction(SIGALRM, &Act, &Old);
     349         166 :     alarm(SecondsToWait);
     350             :   } else if (SecondsToWait == 0)
     351             :     WaitPidOptions = WNOHANG;
     352             : 
     353             :   // Parent process: Wait for the child process to terminate.
     354             :   int status;
     355     2879072 :   ProcessInfo WaitResult;
     356             : 
     357             :   do {
     358     2879072 :     WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
     359     2879072 :   } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
     360             : 
     361     2879072 :   if (WaitResult.Pid != PI.Pid) {
     362     2859770 :     if (WaitResult.Pid == 0) {
     363             :       // Non-blocking wait.
     364     2859769 :       return WaitResult;
     365             :     } else {
     366           1 :       if (SecondsToWait && errno == EINTR) {
     367             :         // Kill the child.
     368           1 :         kill(PI.Pid, SIGKILL);
     369             : 
     370             :         // Turn off the alarm and restore the signal handler
     371           1 :         alarm(0);
     372           1 :         sigaction(SIGALRM, &Old, nullptr);
     373             : 
     374             :         // Wait for child to die
     375           1 :         if (wait(&status) != ChildPid)
     376           0 :           MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
     377             :         else
     378           2 :           MakeErrMsg(ErrMsg, "Child timed out", 0);
     379             : 
     380           1 :         WaitResult.ReturnCode = -2; // Timeout detected
     381           1 :         return WaitResult;
     382           0 :       } else if (errno != EINTR) {
     383           0 :         MakeErrMsg(ErrMsg, "Error waiting for child process");
     384           0 :         WaitResult.ReturnCode = -1;
     385           0 :         return WaitResult;
     386             :       }
     387             :     }
     388             :   }
     389             : 
     390             :   // We exited normally without timeout, so turn off the timer.
     391       19302 :   if (SecondsToWait && !WaitUntilTerminates) {
     392         165 :     alarm(0);
     393         165 :     sigaction(SIGALRM, &Old, nullptr);
     394             :   }
     395             : 
     396             :   // Return the proper exit status. Detect error conditions
     397             :   // so we can return -1 for them and set ErrMsg informatively.
     398             :   int result = 0;
     399       19302 :   if (WIFEXITED(status)) {
     400       19216 :     result = WEXITSTATUS(status);
     401       19216 :     WaitResult.ReturnCode = result;
     402             : 
     403       19216 :     if (result == 127) {
     404           0 :       if (ErrMsg)
     405           0 :         *ErrMsg = llvm::sys::StrError(ENOENT);
     406           0 :       WaitResult.ReturnCode = -1;
     407           0 :       return WaitResult;
     408             :     }
     409       19216 :     if (result == 126) {
     410           0 :       if (ErrMsg)
     411             :         *ErrMsg = "Program could not be executed";
     412           0 :       WaitResult.ReturnCode = -1;
     413           0 :       return WaitResult;
     414             :     }
     415          86 :   } else if (WIFSIGNALED(status)) {
     416          86 :     if (ErrMsg) {
     417          86 :       *ErrMsg = strsignal(WTERMSIG(status));
     418             : #ifdef WCOREDUMP
     419          86 :       if (WCOREDUMP(status))
     420             :         *ErrMsg += " (core dumped)";
     421             : #endif
     422             :     }
     423             :     // Return a special value to indicate that the process received an unhandled
     424             :     // signal during execution as opposed to failing to execute.
     425          86 :     WaitResult.ReturnCode = -2;
     426             :   }
     427       19302 :   return WaitResult;
     428             : }
     429             : 
     430       95825 : std::error_code sys::ChangeStdinToBinary() {
     431             :   // Do nothing, as Unix doesn't differentiate between text and binary.
     432       95825 :   return std::error_code();
     433             : }
     434             : 
     435       29825 : std::error_code sys::ChangeStdoutToBinary() {
     436             :   // Do nothing, as Unix doesn't differentiate between text and binary.
     437       29825 :   return std::error_code();
     438             : }
     439             : 
     440             : std::error_code
     441           2 : llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
     442             :                                  WindowsEncodingMethod Encoding /*unused*/) {
     443             :   std::error_code EC;
     444           4 :   llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
     445             : 
     446           2 :   if (EC)
     447           0 :     return EC;
     448             : 
     449           2 :   OS << Contents;
     450             : 
     451           2 :   if (OS.has_error())
     452             :     return make_error_code(errc::io_error);
     453             : 
     454           2 :   return EC;
     455             : }
     456             : 
     457       13562 : bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
     458             :                                                   ArrayRef<StringRef> Args) {
     459       13562 :   static long ArgMax = sysconf(_SC_ARG_MAX);
     460             :   // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
     461             :   // value for ARG_MAX on a POSIX compliant system.
     462             :   static long ArgMin = _POSIX_ARG_MAX;
     463             : 
     464             :   // This the same baseline used by xargs.
     465             :   long EffectiveArgMax = 128 * 1024;
     466             : 
     467       13562 :   if (EffectiveArgMax > ArgMax)
     468             :     EffectiveArgMax = ArgMax;
     469       13562 :   else if (EffectiveArgMax < ArgMin)
     470             :     EffectiveArgMax = ArgMin;
     471             : 
     472             :   // System says no practical limit.
     473       13562 :   if (ArgMax == -1)
     474             :     return true;
     475             : 
     476             :   // Conservatively account for space required by environment variables.
     477       13562 :   long HalfArgMax = EffectiveArgMax / 2;
     478             : 
     479       13562 :   size_t ArgLength = Program.size() + 1;
     480      962812 :   for (StringRef Arg : Args) {
     481             :     // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
     482             :     // does not have a constant unlike what the man pages would have you
     483             :     // believe. Since this limit is pretty high, perform the check
     484             :     // unconditionally rather than trying to be aggressive and limiting it to
     485             :     // Linux only.
     486      949252 :     if (Arg.size() >= (32 * 4096))
     487             :       return false;
     488             : 
     489      949251 :     ArgLength += Arg.size() + 1;
     490      949251 :     if (ArgLength > size_t(HalfArgMax)) {
     491             :       return false;
     492             :     }
     493             :   }
     494             : 
     495       13560 :   return true;
     496             : }
     497             : }

Generated by: LCOV version 1.13