LLVM API Documentation

Unix/Program.inc
Go to the documentation of this file.
00001 //===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Unix specific portion of the Program class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 //===----------------------------------------------------------------------===//
00015 //=== WARNING: Implementation here must contain only generic UNIX code that
00016 //===          is guaranteed to work on *all* UNIX variants.
00017 //===----------------------------------------------------------------------===//
00018 
00019 #include "Unix.h"
00020 #include "llvm/Support/Compiler.h"
00021 #include "llvm/Support/FileSystem.h"
00022 #include "llvm/Support/raw_ostream.h"
00023 #include <llvm/Config/config.h>
00024 #if HAVE_SYS_STAT_H
00025 #include <sys/stat.h>
00026 #endif
00027 #if HAVE_SYS_RESOURCE_H
00028 #include <sys/resource.h>
00029 #endif
00030 #if HAVE_SIGNAL_H
00031 #include <signal.h>
00032 #endif
00033 #if HAVE_FCNTL_H
00034 #include <fcntl.h>
00035 #endif
00036 #if HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 #ifdef HAVE_POSIX_SPAWN
00040 #ifdef __sun__
00041 #define  _RESTRICT_KYWD
00042 #endif
00043 #include <spawn.h>
00044 #if !defined(__APPLE__)
00045   extern char **environ;
00046 #else
00047 #include <crt_externs.h> // _NSGetEnviron
00048 #endif
00049 #endif
00050 
00051 namespace llvm {
00052 
00053 using namespace sys;
00054 
00055 ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
00056 
00057 // This function just uses the PATH environment variable to find the program.
00058 std::string
00059 sys::FindProgramByName(const std::string& progName) {
00060 
00061   // Check some degenerate cases
00062   if (progName.length() == 0) // no program
00063     return "";
00064   std::string temp = progName;
00065   // Use the given path verbatim if it contains any slashes; this matches
00066   // the behavior of sh(1) and friends.
00067   if (progName.find('/') != std::string::npos)
00068     return temp;
00069 
00070   // At this point, the file name is valid and does not contain slashes. Search
00071   // for it through the directories specified in the PATH environment variable.
00072 
00073   // Get the path. If its empty, we can't do anything to find it.
00074   const char *PathStr = getenv("PATH");
00075   if (!PathStr)
00076     return "";
00077 
00078   // Now we have a colon separated list of directories to search; try them.
00079   size_t PathLen = strlen(PathStr);
00080   while (PathLen) {
00081     // Find the first colon...
00082     const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
00083 
00084     // Check to see if this first directory contains the executable...
00085     SmallString<128> FilePath(PathStr,Colon);
00086     sys::path::append(FilePath, progName);
00087     if (sys::fs::can_execute(Twine(FilePath)))
00088       return FilePath.str();                    // Found the executable!
00089 
00090     // Nope it wasn't in this directory, check the next path in the list!
00091     PathLen -= Colon-PathStr;
00092     PathStr = Colon;
00093 
00094     // Advance past duplicate colons
00095     while (*PathStr == ':') {
00096       PathStr++;
00097       PathLen--;
00098     }
00099   }
00100   return "";
00101 }
00102 
00103 static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) {
00104   if (!Path) // Noop
00105     return false;
00106   std::string File;
00107   if (Path->empty())
00108     // Redirect empty paths to /dev/null
00109     File = "/dev/null";
00110   else
00111     File = *Path;
00112 
00113   // Open the file
00114   int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
00115   if (InFD == -1) {
00116     MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
00117               + (FD == 0 ? "input" : "output"));
00118     return true;
00119   }
00120 
00121   // Install it as the requested FD
00122   if (dup2(InFD, FD) == -1) {
00123     MakeErrMsg(ErrMsg, "Cannot dup2");
00124     close(InFD);
00125     return true;
00126   }
00127   close(InFD);      // Close the original FD
00128   return false;
00129 }
00130 
00131 #ifdef HAVE_POSIX_SPAWN
00132 static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
00133                           posix_spawn_file_actions_t *FileActions) {
00134   if (!Path) // Noop
00135     return false;
00136   const char *File;
00137   if (Path->empty())
00138     // Redirect empty paths to /dev/null
00139     File = "/dev/null";
00140   else
00141     File = Path->c_str();
00142 
00143   if (int Err = posix_spawn_file_actions_addopen(
00144           FileActions, FD, File,
00145           FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
00146     return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
00147   return false;
00148 }
00149 #endif
00150 
00151 static void TimeOutHandler(int Sig) {
00152 }
00153 
00154 static void SetMemoryLimits (unsigned size)
00155 {
00156 #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
00157   struct rlimit r;
00158   __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
00159 
00160   // Heap size
00161   getrlimit (RLIMIT_DATA, &r);
00162   r.rlim_cur = limit;
00163   setrlimit (RLIMIT_DATA, &r);
00164 #ifdef RLIMIT_RSS
00165   // Resident set size.
00166   getrlimit (RLIMIT_RSS, &r);
00167   r.rlim_cur = limit;
00168   setrlimit (RLIMIT_RSS, &r);
00169 #endif
00170 #ifdef RLIMIT_AS  // e.g. NetBSD doesn't have it.
00171   // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb
00172   // of virtual memory for shadow memory mapping.
00173 #if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD
00174   // Virtual memory.
00175   getrlimit (RLIMIT_AS, &r);
00176   r.rlim_cur = limit;
00177   setrlimit (RLIMIT_AS, &r);
00178 #endif
00179 #endif
00180 #endif
00181 }
00182 
00183 }
00184 
00185 static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
00186                     const char **envp, const StringRef **redirects,
00187                     unsigned memoryLimit, std::string *ErrMsg) {
00188   if (!llvm::sys::fs::exists(Program)) {
00189     if (ErrMsg)
00190       *ErrMsg = std::string("Executable \"") + Program.str() +
00191                 std::string("\" doesn't exist!");
00192     return false;
00193   }
00194 
00195   // If this OS has posix_spawn and there is no memory limit being implied, use
00196   // posix_spawn.  It is more efficient than fork/exec.
00197 #ifdef HAVE_POSIX_SPAWN
00198   if (memoryLimit == 0) {
00199     posix_spawn_file_actions_t FileActionsStore;
00200     posix_spawn_file_actions_t *FileActions = nullptr;
00201 
00202     // If we call posix_spawn_file_actions_addopen we have to make sure the
00203     // c strings we pass to it stay alive until the call to posix_spawn,
00204     // so we copy any StringRefs into this variable.
00205     std::string RedirectsStorage[3];
00206 
00207     if (redirects) {
00208       std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
00209       for (int I = 0; I < 3; ++I) {
00210         if (redirects[I]) {
00211           RedirectsStorage[I] = *redirects[I];
00212           RedirectsStr[I] = &RedirectsStorage[I];
00213         }
00214       }
00215 
00216       FileActions = &FileActionsStore;
00217       posix_spawn_file_actions_init(FileActions);
00218 
00219       // Redirect stdin/stdout.
00220       if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
00221           RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
00222         return false;
00223       if (redirects[1] == nullptr || redirects[2] == nullptr ||
00224           *redirects[1] != *redirects[2]) {
00225         // Just redirect stderr
00226         if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
00227           return false;
00228       } else {
00229         // If stdout and stderr should go to the same place, redirect stderr
00230         // to the FD already open for stdout.
00231         if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
00232           return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
00233       }
00234     }
00235 
00236     if (!envp)
00237 #if !defined(__APPLE__)
00238       envp = const_cast<const char **>(environ);
00239 #else
00240       // environ is missing in dylibs.
00241       envp = const_cast<const char **>(*_NSGetEnviron());
00242 #endif
00243 
00244     // Explicitly initialized to prevent what appears to be a valgrind false
00245     // positive.
00246     pid_t PID = 0;
00247     int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
00248                           /*attrp*/nullptr, const_cast<char **>(args),
00249                           const_cast<char **>(envp));
00250 
00251     if (FileActions)
00252       posix_spawn_file_actions_destroy(FileActions);
00253 
00254     if (Err)
00255      return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
00256 
00257     PI.Pid = PID;
00258 
00259     return true;
00260   }
00261 #endif
00262 
00263   // Create a child process.
00264   int child = fork();
00265   switch (child) {
00266     // An error occurred:  Return to the caller.
00267     case -1:
00268       MakeErrMsg(ErrMsg, "Couldn't fork");
00269       return false;
00270 
00271     // Child process: Execute the program.
00272     case 0: {
00273       // Redirect file descriptors...
00274       if (redirects) {
00275         // Redirect stdin
00276         if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; }
00277         // Redirect stdout
00278         if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; }
00279         if (redirects[1] && redirects[2] &&
00280             *(redirects[1]) == *(redirects[2])) {
00281           // If stdout and stderr should go to the same place, redirect stderr
00282           // to the FD already open for stdout.
00283           if (-1 == dup2(1,2)) {
00284             MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
00285             return false;
00286           }
00287         } else {
00288           // Just redirect stderr
00289           if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; }
00290         }
00291       }
00292 
00293       // Set memory limits
00294       if (memoryLimit!=0) {
00295         SetMemoryLimits(memoryLimit);
00296       }
00297 
00298       // Execute!
00299       std::string PathStr = Program;
00300       if (envp != nullptr)
00301         execve(PathStr.c_str(),
00302                const_cast<char **>(args),
00303                const_cast<char **>(envp));
00304       else
00305         execv(PathStr.c_str(),
00306               const_cast<char **>(args));
00307       // If the execve() failed, we should exit. Follow Unix protocol and
00308       // return 127 if the executable was not found, and 126 otherwise.
00309       // Use _exit rather than exit so that atexit functions and static
00310       // object destructors cloned from the parent process aren't
00311       // redundantly run, and so that any data buffered in stdio buffers
00312       // cloned from the parent aren't redundantly written out.
00313       _exit(errno == ENOENT ? 127 : 126);
00314     }
00315 
00316     // Parent process: Break out of the switch to do our processing.
00317     default:
00318       break;
00319   }
00320 
00321   PI.Pid = child;
00322 
00323   return true;
00324 }
00325 
00326 namespace llvm {
00327 
00328 ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
00329                       bool WaitUntilTerminates, std::string *ErrMsg) {
00330 #ifdef HAVE_SYS_WAIT_H
00331   struct sigaction Act, Old;
00332   assert(PI.Pid && "invalid pid to wait on, process not started?");
00333 
00334   int WaitPidOptions = 0;
00335   pid_t ChildPid = PI.Pid;
00336   if (WaitUntilTerminates) {
00337     SecondsToWait = 0;
00338     ChildPid = -1; // mimic a wait() using waitpid()
00339   } else if (SecondsToWait) {
00340     // Install a timeout handler.  The handler itself does nothing, but the
00341     // simple fact of having a handler at all causes the wait below to return
00342     // with EINTR, unlike if we used SIG_IGN.
00343     memset(&Act, 0, sizeof(Act));
00344     Act.sa_handler = TimeOutHandler;
00345     sigemptyset(&Act.sa_mask);
00346     sigaction(SIGALRM, &Act, &Old);
00347     alarm(SecondsToWait);
00348   } else if (SecondsToWait == 0)
00349     WaitPidOptions = WNOHANG;
00350 
00351   // Parent process: Wait for the child process to terminate.
00352   int status;
00353   ProcessInfo WaitResult;
00354 
00355   do {
00356     WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
00357   } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
00358 
00359   if (WaitResult.Pid != PI.Pid) {
00360     if (WaitResult.Pid == 0) {
00361       // Non-blocking wait.
00362       return WaitResult;
00363     } else {
00364       if (SecondsToWait && errno == EINTR) {
00365         // Kill the child.
00366         kill(PI.Pid, SIGKILL);
00367 
00368         // Turn off the alarm and restore the signal handler
00369         alarm(0);
00370         sigaction(SIGALRM, &Old, nullptr);
00371 
00372         // Wait for child to die
00373         if (wait(&status) != ChildPid)
00374           MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
00375         else
00376           MakeErrMsg(ErrMsg, "Child timed out", 0);
00377 
00378         WaitResult.ReturnCode = -2; // Timeout detected
00379         return WaitResult;
00380       } else if (errno != EINTR) {
00381         MakeErrMsg(ErrMsg, "Error waiting for child process");
00382         WaitResult.ReturnCode = -1;
00383         return WaitResult;
00384       }
00385     }
00386   }
00387 
00388   // We exited normally without timeout, so turn off the timer.
00389   if (SecondsToWait && !WaitUntilTerminates) {
00390     alarm(0);
00391     sigaction(SIGALRM, &Old, nullptr);
00392   }
00393 
00394   // Return the proper exit status. Detect error conditions
00395   // so we can return -1 for them and set ErrMsg informatively.
00396   int result = 0;
00397   if (WIFEXITED(status)) {
00398     result = WEXITSTATUS(status);
00399     WaitResult.ReturnCode = result;
00400 
00401     if (result == 127) {
00402       if (ErrMsg)
00403         *ErrMsg = llvm::sys::StrError(ENOENT);
00404       WaitResult.ReturnCode = -1;
00405       return WaitResult;
00406     }
00407     if (result == 126) {
00408       if (ErrMsg)
00409         *ErrMsg = "Program could not be executed";
00410       WaitResult.ReturnCode = -1;
00411       return WaitResult;
00412     }
00413   } else if (WIFSIGNALED(status)) {
00414     if (ErrMsg) {
00415       *ErrMsg = strsignal(WTERMSIG(status));
00416 #ifdef WCOREDUMP
00417       if (WCOREDUMP(status))
00418         *ErrMsg += " (core dumped)";
00419 #endif
00420     }
00421     // Return a special value to indicate that the process received an unhandled
00422     // signal during execution as opposed to failing to execute.
00423     WaitResult.ReturnCode = -2;
00424   }
00425 #else
00426   if (ErrMsg)
00427     *ErrMsg = "Program::Wait is not implemented on this platform yet!";
00428   ProcessInfo WaitResult;
00429   WaitResult.ReturnCode = -2;
00430 #endif
00431   return WaitResult;
00432 }
00433 
00434   std::error_code sys::ChangeStdinToBinary(){
00435   // Do nothing, as Unix doesn't differentiate between text and binary.
00436     return std::error_code();
00437 }
00438 
00439   std::error_code sys::ChangeStdoutToBinary(){
00440   // Do nothing, as Unix doesn't differentiate between text and binary.
00441     return std::error_code();
00442 }
00443 
00444 std::error_code
00445 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
00446                                  WindowsEncodingMethod Encoding /*unused*/) {
00447   std::error_code EC;
00448   llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
00449 
00450   if (EC)
00451     return EC;
00452 
00453   OS << Contents;
00454 
00455   if (OS.has_error())
00456     return std::make_error_code(std::errc::io_error);
00457 
00458   return EC;
00459 }
00460 
00461 bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {
00462   static long ArgMax = sysconf(_SC_ARG_MAX);
00463 
00464   // System says no practical limit.
00465   if (ArgMax == -1)
00466     return true;
00467 
00468   // Conservatively account for space required by environment variables.
00469   long HalfArgMax = ArgMax / 2;
00470 
00471   size_t ArgLength = 0;
00472   for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();
00473        I != E; ++I) {
00474     ArgLength += strlen(*I) + 1;
00475     if (ArgLength > size_t(HalfArgMax)) {
00476       return false;
00477     }
00478   }
00479   return true;
00480 }
00481 }