Home | History | Annotate | Download | only in Unix
      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 ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
     68 
     69 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   if (Name.find('/') != StringRef::npos)
     75     return std::string(Name);
     76 
     77   SmallVector<StringRef, 16> EnvironmentPaths;
     78   if (Paths.empty())
     79     if (const char *PathEnv = std::getenv("PATH")) {
     80       SplitString(PathEnv, EnvironmentPaths, ":");
     81       Paths = EnvironmentPaths;
     82     }
     83 
     84   for (auto Path : Paths) {
     85     if (Path.empty())
     86       continue;
     87 
     88     // Check to see if this first directory contains the executable...
     89     SmallString<128> FilePath(Path);
     90     sys::path::append(FilePath, Name);
     91     if (sys::fs::can_execute(FilePath.c_str()))
     92       return std::string(FilePath.str()); // Found the executable!
     93   }
     94   return errc::no_such_file_or_directory;
     95 }
     96 
     97 static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
     98   if (!Path) // Noop
     99     return false;
    100   std::string File;
    101   if (Path->empty())
    102     // Redirect empty paths to /dev/null
    103     File = "/dev/null";
    104   else
    105     File = *Path;
    106 
    107   // Open the file
    108   int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
    109   if (InFD == -1) {
    110     MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
    111               + (FD == 0 ? "input" : "output"));
    112     return true;
    113   }
    114 
    115   // Install it as the requested FD
    116   if (dup2(InFD, FD) == -1) {
    117     MakeErrMsg(ErrMsg, "Cannot dup2");
    118     close(InFD);
    119     return true;
    120   }
    121   close(InFD);      // Close the original FD
    122   return false;
    123 }
    124 
    125 #ifdef HAVE_POSIX_SPAWN
    126 static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
    127                           posix_spawn_file_actions_t *FileActions) {
    128   if (!Path) // Noop
    129     return false;
    130   const char *File;
    131   if (Path->empty())
    132     // Redirect empty paths to /dev/null
    133     File = "/dev/null";
    134   else
    135     File = Path->c_str();
    136 
    137   if (int Err = posix_spawn_file_actions_addopen(
    138           FileActions, FD, File,
    139           FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
    140     return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
    141   return false;
    142 }
    143 #endif
    144 
    145 static void TimeOutHandler(int Sig) {
    146 }
    147 
    148 static void SetMemoryLimits(unsigned size) {
    149 #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
    150   struct rlimit r;
    151   __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
    152 
    153   // Heap size
    154   getrlimit (RLIMIT_DATA, &r);
    155   r.rlim_cur = limit;
    156   setrlimit (RLIMIT_DATA, &r);
    157 #ifdef RLIMIT_RSS
    158   // Resident set size.
    159   getrlimit (RLIMIT_RSS, &r);
    160   r.rlim_cur = limit;
    161   setrlimit (RLIMIT_RSS, &r);
    162 #endif
    163 #endif
    164 }
    165 
    166 }
    167 
    168 static std::vector<const char *>
    169 toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
    170   std::vector<const char *> Result;
    171   for (StringRef S : Strings)
    172     Result.push_back(Saver.save(S).data());
    173   Result.push_back(nullptr);
    174   return Result;
    175 }
    176 
    177 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   if (!llvm::sys::fs::exists(Program)) {
    182     if (ErrMsg)
    183       *ErrMsg = std::string("Executable \"") + Program.str() +
    184                 std::string("\" doesn't exist!");
    185     return false;
    186   }
    187 
    188   BumpPtrAllocator Allocator;
    189   StringSaver Saver(Allocator);
    190   std::vector<const char *> ArgVector, EnvVector;
    191   const char **Argv = nullptr;
    192   const char **Envp = nullptr;
    193   ArgVector = toNullTerminatedCStringArray(Args, Saver);
    194   Argv = ArgVector.data();
    195   if (Env) {
    196     EnvVector = toNullTerminatedCStringArray(*Env, Saver);
    197     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   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     std::string RedirectsStorage[3];
    211 
    212     if (!Redirects.empty()) {
    213       assert(Redirects.size() == 3);
    214       std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
    215       for (int I = 0; I < 3; ++I) {
    216         if (Redirects[I]) {
    217           RedirectsStorage[I] = *Redirects[I];
    218           RedirectsStr[I] = &RedirectsStorage[I];
    219         }
    220       }
    221 
    222       FileActions = &FileActionsStore;
    223       posix_spawn_file_actions_init(FileActions);
    224 
    225       // Redirect stdin/stdout.
    226       if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
    227           RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
    228         return false;
    229       if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
    230         // Just redirect stderr
    231         if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
    232           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         if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
    237           return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
    238       }
    239     }
    240 
    241     if (!Envp)
    242 #if !USE_NSGETENVIRON
    243       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     pid_t PID = 0;
    252     int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
    253                           /*attrp*/ nullptr, const_cast<char **>(Argv),
    254                           const_cast<char **>(Envp));
    255 
    256     if (FileActions)
    257       posix_spawn_file_actions_destroy(FileActions);
    258 
    259     if (Err)
    260      return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
    261 
    262     PI.Pid = PID;
    263     PI.Process = PID;
    264 
    265     return true;
    266   }
    267 #endif
    268 
    269   // Create a child process.
    270   int child = fork();
    271   switch (child) {
    272     // An error occurred:  Return to the caller.
    273     case -1:
    274       MakeErrMsg(ErrMsg, "Couldn't fork");
    275       return false;
    276 
    277     // Child process: Execute the program.
    278     case 0: {
    279       // Redirect file descriptors...
    280       if (!Redirects.empty()) {
    281         // Redirect stdin
    282         if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
    283         // Redirect stdout
    284         if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
    285         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           if (-1 == dup2(1,2)) {
    289             MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
    290             return false;
    291           }
    292         } else {
    293           // Just redirect stderr
    294           if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
    295         }
    296       }
    297 
    298       // Set memory limits
    299       if (MemoryLimit!=0) {
    300         SetMemoryLimits(MemoryLimit);
    301       }
    302 
    303       // Execute!
    304       std::string PathStr = Program;
    305       if (Envp != nullptr)
    306         execve(PathStr.c_str(), const_cast<char **>(Argv),
    307                const_cast<char **>(Envp));
    308       else
    309         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       _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   PI.Pid = child;
    325   PI.Process = child;
    326 
    327   return true;
    328 }
    329 
    330 namespace llvm {
    331 
    332 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   pid_t ChildPid = PI.Pid;
    339   if (WaitUntilTerminates) {
    340     SecondsToWait = 0;
    341   } 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     memset(&Act, 0, sizeof(Act));
    346     Act.sa_handler = TimeOutHandler;
    347     sigemptyset(&Act.sa_mask);
    348     sigaction(SIGALRM, &Act, &Old);
    349     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   ProcessInfo WaitResult;
    356 
    357   do {
    358     WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
    359   } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
    360 
    361   if (WaitResult.Pid != PI.Pid) {
    362     if (WaitResult.Pid == 0) {
    363       // Non-blocking wait.
    364       return WaitResult;
    365     } else {
    366       if (SecondsToWait && errno == EINTR) {
    367         // Kill the child.
    368         kill(PI.Pid, SIGKILL);
    369 
    370         // Turn off the alarm and restore the signal handler
    371         alarm(0);
    372         sigaction(SIGALRM, &Old, nullptr);
    373 
    374         // Wait for child to die
    375         if (wait(&status) != ChildPid)
    376           MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
    377         else
    378           MakeErrMsg(ErrMsg, "Child timed out", 0);
    379 
    380         WaitResult.ReturnCode = -2; // Timeout detected
    381         return WaitResult;
    382       } else if (errno != EINTR) {
    383         MakeErrMsg(ErrMsg, "Error waiting for child process");
    384         WaitResult.ReturnCode = -1;
    385         return WaitResult;
    386       }
    387     }
    388   }
    389 
    390   // We exited normally without timeout, so turn off the timer.
    391   if (SecondsToWait && !WaitUntilTerminates) {
    392     alarm(0);
    393     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   if (WIFEXITED(status)) {
    400     result = WEXITSTATUS(status);
    401     WaitResult.ReturnCode = result;
    402 
    403     if (result == 127) {
    404       if (ErrMsg)
    405         *ErrMsg = llvm::sys::StrError(ENOENT);
    406       WaitResult.ReturnCode = -1;
    407       return WaitResult;
    408     }
    409     if (result == 126) {
    410       if (ErrMsg)
    411         *ErrMsg = "Program could not be executed";
    412       WaitResult.ReturnCode = -1;
    413       return WaitResult;
    414     }
    415   } else if (WIFSIGNALED(status)) {
    416     if (ErrMsg) {
    417       *ErrMsg = strsignal(WTERMSIG(status));
    418 #ifdef WCOREDUMP
    419       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     WaitResult.ReturnCode = -2;
    426   }
    427   return WaitResult;
    428 }
    429 
    430 std::error_code sys::ChangeStdinToBinary() {
    431   // Do nothing, as Unix doesn't differentiate between text and binary.
    432   return std::error_code();
    433 }
    434 
    435 std::error_code sys::ChangeStdoutToBinary() {
    436   // Do nothing, as Unix doesn't differentiate between text and binary.
    437   return std::error_code();
    438 }
    439 
    440 std::error_code
    441 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
    442                                  WindowsEncodingMethod Encoding /*unused*/) {
    443   std::error_code EC;
    444   llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
    445 
    446   if (EC)
    447     return EC;
    448 
    449   OS << Contents;
    450 
    451   if (OS.has_error())
    452     return make_error_code(errc::io_error);
    453 
    454   return EC;
    455 }
    456 
    457 bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
    458                                                   ArrayRef<StringRef> Args) {
    459   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   if (EffectiveArgMax > ArgMax)
    468     EffectiveArgMax = ArgMax;
    469   else if (EffectiveArgMax < ArgMin)
    470     EffectiveArgMax = ArgMin;
    471 
    472   // System says no practical limit.
    473   if (ArgMax == -1)
    474     return true;
    475 
    476   // Conservatively account for space required by environment variables.
    477   long HalfArgMax = EffectiveArgMax / 2;
    478 
    479   size_t ArgLength = Program.size() + 1;
    480   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     if (Arg.size() >= (32 * 4096))
    487       return false;
    488 
    489     ArgLength += Arg.size() + 1;
    490     if (ArgLength > size_t(HalfArgMax)) {
    491       return false;
    492     }
    493   }
    494 
    495   return true;
    496 }
    497 }
    498