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