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