1218885Sdim//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file implements the Unix specific portion of the Program class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim//===----------------------------------------------------------------------===// 15218885Sdim//=== WARNING: Implementation here must contain only generic UNIX code that 16218885Sdim//=== is guaranteed to work on *all* UNIX variants. 17218885Sdim//===----------------------------------------------------------------------===// 18218885Sdim 19249423Sdim#include "Unix.h" 20249423Sdim#include "llvm/Support/Compiler.h" 21249423Sdim#include "llvm/Support/FileSystem.h" 22218885Sdim#include <llvm/Config/config.h> 23218885Sdim#if HAVE_SYS_STAT_H 24218885Sdim#include <sys/stat.h> 25218885Sdim#endif 26218885Sdim#if HAVE_SYS_RESOURCE_H 27218885Sdim#include <sys/resource.h> 28218885Sdim#endif 29218885Sdim#if HAVE_SIGNAL_H 30218885Sdim#include <signal.h> 31218885Sdim#endif 32218885Sdim#if HAVE_FCNTL_H 33218885Sdim#include <fcntl.h> 34218885Sdim#endif 35251662Sdim#if HAVE_UNISTD_H 36251662Sdim#include <unistd.h> 37251662Sdim#endif 38218885Sdim#ifdef HAVE_POSIX_SPAWN 39218885Sdim#include <spawn.h> 40218885Sdim#if !defined(__APPLE__) 41218885Sdim extern char **environ; 42218885Sdim#else 43218885Sdim#include <crt_externs.h> // _NSGetEnviron 44218885Sdim#endif 45218885Sdim#endif 46218885Sdim 47218885Sdimnamespace llvm { 48218885Sdimusing namespace sys; 49218885Sdim 50218885SdimProgram::Program() : Data_(0) {} 51218885Sdim 52218885SdimProgram::~Program() {} 53218885Sdim 54218885Sdim// This function just uses the PATH environment variable to find the program. 55218885SdimPath 56218885SdimProgram::FindProgramByName(const std::string& progName) { 57218885Sdim 58218885Sdim // Check some degenerate cases 59218885Sdim if (progName.length() == 0) // no program 60218885Sdim return Path(); 61218885Sdim Path temp; 62218885Sdim if (!temp.set(progName)) // invalid name 63218885Sdim return Path(); 64218885Sdim // Use the given path verbatim if it contains any slashes; this matches 65218885Sdim // the behavior of sh(1) and friends. 66218885Sdim if (progName.find('/') != std::string::npos) 67218885Sdim return temp; 68218885Sdim 69218885Sdim // At this point, the file name is valid and does not contain slashes. Search 70218885Sdim // for it through the directories specified in the PATH environment variable. 71218885Sdim 72218885Sdim // Get the path. If its empty, we can't do anything to find it. 73218885Sdim const char *PathStr = getenv("PATH"); 74218885Sdim if (PathStr == 0) 75218885Sdim return Path(); 76218885Sdim 77218885Sdim // Now we have a colon separated list of directories to search; try them. 78218885Sdim size_t PathLen = strlen(PathStr); 79218885Sdim while (PathLen) { 80218885Sdim // Find the first colon... 81218885Sdim const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); 82218885Sdim 83218885Sdim // Check to see if this first directory contains the executable... 84218885Sdim Path FilePath; 85218885Sdim if (FilePath.set(std::string(PathStr,Colon))) { 86218885Sdim FilePath.appendComponent(progName); 87218885Sdim if (FilePath.canExecute()) 88218885Sdim return FilePath; // Found the executable! 89218885Sdim } 90218885Sdim 91218885Sdim // Nope it wasn't in this directory, check the next path in the list! 92218885Sdim PathLen -= Colon-PathStr; 93218885Sdim PathStr = Colon; 94218885Sdim 95218885Sdim // Advance past duplicate colons 96218885Sdim while (*PathStr == ':') { 97218885Sdim PathStr++; 98218885Sdim PathLen--; 99218885Sdim } 100218885Sdim } 101218885Sdim return Path(); 102218885Sdim} 103218885Sdim 104218885Sdimstatic bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { 105218885Sdim if (Path == 0) // Noop 106218885Sdim return false; 107218885Sdim const char *File; 108218885Sdim if (Path->isEmpty()) 109218885Sdim // Redirect empty paths to /dev/null 110218885Sdim File = "/dev/null"; 111218885Sdim else 112218885Sdim File = Path->c_str(); 113218885Sdim 114218885Sdim // Open the file 115218885Sdim int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); 116218885Sdim if (InFD == -1) { 117218885Sdim MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for " 118218885Sdim + (FD == 0 ? "input" : "output")); 119218885Sdim return true; 120218885Sdim } 121218885Sdim 122218885Sdim // Install it as the requested FD 123218885Sdim if (dup2(InFD, FD) == -1) { 124218885Sdim MakeErrMsg(ErrMsg, "Cannot dup2"); 125218885Sdim close(InFD); 126218885Sdim return true; 127218885Sdim } 128218885Sdim close(InFD); // Close the original FD 129218885Sdim return false; 130218885Sdim} 131218885Sdim 132218885Sdim#ifdef HAVE_POSIX_SPAWN 133218885Sdimstatic bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, 134221345Sdim posix_spawn_file_actions_t *FileActions) { 135218885Sdim if (Path == 0) // Noop 136218885Sdim return false; 137218885Sdim const char *File; 138218885Sdim if (Path->isEmpty()) 139218885Sdim // Redirect empty paths to /dev/null 140218885Sdim File = "/dev/null"; 141218885Sdim else 142218885Sdim File = Path->c_str(); 143218885Sdim 144221345Sdim if (int Err = posix_spawn_file_actions_addopen(FileActions, FD, 145218885Sdim File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) 146218885Sdim return MakeErrMsg(ErrMsg, "Cannot dup2", Err); 147218885Sdim return false; 148218885Sdim} 149218885Sdim#endif 150218885Sdim 151218885Sdimstatic void TimeOutHandler(int Sig) { 152218885Sdim} 153218885Sdim 154218885Sdimstatic void SetMemoryLimits (unsigned size) 155218885Sdim{ 156218885Sdim#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT 157218885Sdim struct rlimit r; 158218885Sdim __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; 159218885Sdim 160218885Sdim // Heap size 161218885Sdim getrlimit (RLIMIT_DATA, &r); 162218885Sdim r.rlim_cur = limit; 163218885Sdim setrlimit (RLIMIT_DATA, &r); 164218885Sdim#ifdef RLIMIT_RSS 165218885Sdim // Resident set size. 166218885Sdim getrlimit (RLIMIT_RSS, &r); 167218885Sdim r.rlim_cur = limit; 168218885Sdim setrlimit (RLIMIT_RSS, &r); 169218885Sdim#endif 170218885Sdim#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. 171249423Sdim // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb 172249423Sdim // of virtual memory for shadow memory mapping. 173249423Sdim#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD 174218885Sdim // Virtual memory. 175218885Sdim getrlimit (RLIMIT_AS, &r); 176218885Sdim r.rlim_cur = limit; 177218885Sdim setrlimit (RLIMIT_AS, &r); 178218885Sdim#endif 179218885Sdim#endif 180249423Sdim#endif 181218885Sdim} 182218885Sdim 183218885Sdimbool 184218885SdimProgram::Execute(const Path &path, const char **args, const char **envp, 185218885Sdim const Path **redirects, unsigned memoryLimit, 186218885Sdim std::string *ErrMsg) { 187218885Sdim // If this OS has posix_spawn and there is no memory limit being implied, use 188218885Sdim // posix_spawn. It is more efficient than fork/exec. 189218885Sdim#ifdef HAVE_POSIX_SPAWN 190218885Sdim if (memoryLimit == 0) { 191221345Sdim posix_spawn_file_actions_t FileActionsStore; 192221345Sdim posix_spawn_file_actions_t *FileActions = 0; 193218885Sdim 194218885Sdim if (redirects) { 195221345Sdim FileActions = &FileActionsStore; 196221345Sdim posix_spawn_file_actions_init(FileActions); 197221345Sdim 198218885Sdim // Redirect stdin/stdout. 199218885Sdim if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || 200218885Sdim RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) 201218885Sdim return false; 202218885Sdim if (redirects[1] == 0 || redirects[2] == 0 || 203218885Sdim *redirects[1] != *redirects[2]) { 204218885Sdim // Just redirect stderr 205218885Sdim if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; 206218885Sdim } else { 207218885Sdim // If stdout and stderr should go to the same place, redirect stderr 208218885Sdim // to the FD already open for stdout. 209221345Sdim if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2)) 210218885Sdim return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); 211218885Sdim } 212218885Sdim } 213218885Sdim 214218885Sdim if (!envp) 215218885Sdim#if !defined(__APPLE__) 216218885Sdim envp = const_cast<const char **>(environ); 217218885Sdim#else 218218885Sdim // environ is missing in dylibs. 219218885Sdim envp = const_cast<const char **>(*_NSGetEnviron()); 220218885Sdim#endif 221218885Sdim 222218885Sdim // Explicitly initialized to prevent what appears to be a valgrind false 223218885Sdim // positive. 224218885Sdim pid_t PID = 0; 225221345Sdim int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, 226218885Sdim const_cast<char **>(args), const_cast<char **>(envp)); 227218885Sdim 228221345Sdim if (FileActions) 229221345Sdim posix_spawn_file_actions_destroy(FileActions); 230218885Sdim 231218885Sdim if (Err) 232218885Sdim return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); 233218885Sdim 234218885Sdim Data_ = reinterpret_cast<void*>(PID); 235218885Sdim return true; 236218885Sdim } 237218885Sdim#endif 238218885Sdim 239218885Sdim // Create a child process. 240218885Sdim int child = fork(); 241218885Sdim switch (child) { 242221345Sdim // An error occurred: Return to the caller. 243218885Sdim case -1: 244218885Sdim MakeErrMsg(ErrMsg, "Couldn't fork"); 245218885Sdim return false; 246218885Sdim 247218885Sdim // Child process: Execute the program. 248218885Sdim case 0: { 249218885Sdim // Redirect file descriptors... 250218885Sdim if (redirects) { 251218885Sdim // Redirect stdin 252218885Sdim if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } 253218885Sdim // Redirect stdout 254218885Sdim if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } 255218885Sdim if (redirects[1] && redirects[2] && 256218885Sdim *(redirects[1]) == *(redirects[2])) { 257218885Sdim // If stdout and stderr should go to the same place, redirect stderr 258218885Sdim // to the FD already open for stdout. 259218885Sdim if (-1 == dup2(1,2)) { 260218885Sdim MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); 261218885Sdim return false; 262218885Sdim } 263218885Sdim } else { 264218885Sdim // Just redirect stderr 265218885Sdim if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } 266218885Sdim } 267218885Sdim } 268218885Sdim 269218885Sdim // Set memory limits 270218885Sdim if (memoryLimit!=0) { 271218885Sdim SetMemoryLimits(memoryLimit); 272218885Sdim } 273218885Sdim 274218885Sdim // Execute! 275218885Sdim if (envp != 0) 276218885Sdim execve(path.c_str(), 277218885Sdim const_cast<char **>(args), 278218885Sdim const_cast<char **>(envp)); 279218885Sdim else 280218885Sdim execv(path.c_str(), 281218885Sdim const_cast<char **>(args)); 282218885Sdim // If the execve() failed, we should exit. Follow Unix protocol and 283218885Sdim // return 127 if the executable was not found, and 126 otherwise. 284218885Sdim // Use _exit rather than exit so that atexit functions and static 285218885Sdim // object destructors cloned from the parent process aren't 286218885Sdim // redundantly run, and so that any data buffered in stdio buffers 287218885Sdim // cloned from the parent aren't redundantly written out. 288218885Sdim _exit(errno == ENOENT ? 127 : 126); 289218885Sdim } 290218885Sdim 291218885Sdim // Parent process: Break out of the switch to do our processing. 292218885Sdim default: 293218885Sdim break; 294218885Sdim } 295218885Sdim 296218885Sdim Data_ = reinterpret_cast<void*>(child); 297218885Sdim 298218885Sdim return true; 299218885Sdim} 300218885Sdim 301218885Sdimint 302218885SdimProgram::Wait(const sys::Path &path, 303218885Sdim unsigned secondsToWait, 304218885Sdim std::string* ErrMsg) 305218885Sdim{ 306218885Sdim#ifdef HAVE_SYS_WAIT_H 307218885Sdim struct sigaction Act, Old; 308218885Sdim 309218885Sdim if (Data_ == 0) { 310218885Sdim MakeErrMsg(ErrMsg, "Process not started!"); 311218885Sdim return -1; 312218885Sdim } 313218885Sdim 314218885Sdim // Install a timeout handler. The handler itself does nothing, but the simple 315218885Sdim // fact of having a handler at all causes the wait below to return with EINTR, 316218885Sdim // unlike if we used SIG_IGN. 317218885Sdim if (secondsToWait) { 318218885Sdim memset(&Act, 0, sizeof(Act)); 319218885Sdim Act.sa_handler = TimeOutHandler; 320218885Sdim sigemptyset(&Act.sa_mask); 321218885Sdim sigaction(SIGALRM, &Act, &Old); 322218885Sdim alarm(secondsToWait); 323218885Sdim } 324218885Sdim 325218885Sdim // Parent process: Wait for the child process to terminate. 326218885Sdim int status; 327218885Sdim uint64_t pid = reinterpret_cast<uint64_t>(Data_); 328218885Sdim pid_t child = static_cast<pid_t>(pid); 329218885Sdim while (waitpid(pid, &status, 0) != child) 330218885Sdim if (secondsToWait && errno == EINTR) { 331218885Sdim // Kill the child. 332218885Sdim kill(child, SIGKILL); 333218885Sdim 334218885Sdim // Turn off the alarm and restore the signal handler 335218885Sdim alarm(0); 336218885Sdim sigaction(SIGALRM, &Old, 0); 337218885Sdim 338218885Sdim // Wait for child to die 339218885Sdim if (wait(&status) != child) 340218885Sdim MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); 341218885Sdim else 342218885Sdim MakeErrMsg(ErrMsg, "Child timed out", 0); 343218885Sdim 344223017Sdim return -2; // Timeout detected 345218885Sdim } else if (errno != EINTR) { 346218885Sdim MakeErrMsg(ErrMsg, "Error waiting for child process"); 347218885Sdim return -1; 348218885Sdim } 349218885Sdim 350218885Sdim // We exited normally without timeout, so turn off the timer. 351218885Sdim if (secondsToWait) { 352218885Sdim alarm(0); 353218885Sdim sigaction(SIGALRM, &Old, 0); 354218885Sdim } 355218885Sdim 356218885Sdim // Return the proper exit status. Detect error conditions 357218885Sdim // so we can return -1 for them and set ErrMsg informatively. 358218885Sdim int result = 0; 359218885Sdim if (WIFEXITED(status)) { 360218885Sdim result = WEXITSTATUS(status); 361218885Sdim#ifdef HAVE_POSIX_SPAWN 362218885Sdim // The posix_spawn child process returns 127 on any kind of error. 363218885Sdim // Following the POSIX convention for command-line tools (which posix_spawn 364218885Sdim // itself apparently does not), check to see if the failure was due to some 365218885Sdim // reason other than the file not existing, and return 126 in this case. 366218885Sdim bool Exists; 367218885Sdim if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) 368218885Sdim result = 126; 369218885Sdim#endif 370218885Sdim if (result == 127) { 371218885Sdim if (ErrMsg) 372218885Sdim *ErrMsg = llvm::sys::StrError(ENOENT); 373218885Sdim return -1; 374218885Sdim } 375218885Sdim if (result == 126) { 376218885Sdim if (ErrMsg) 377218885Sdim *ErrMsg = "Program could not be executed"; 378218885Sdim return -1; 379218885Sdim } 380218885Sdim } else if (WIFSIGNALED(status)) { 381218885Sdim if (ErrMsg) { 382218885Sdim *ErrMsg = strsignal(WTERMSIG(status)); 383218885Sdim#ifdef WCOREDUMP 384218885Sdim if (WCOREDUMP(status)) 385218885Sdim *ErrMsg += " (core dumped)"; 386218885Sdim#endif 387218885Sdim } 388223017Sdim // Return a special value to indicate that the process received an unhandled 389223017Sdim // signal during execution as opposed to failing to execute. 390223017Sdim return -2; 391218885Sdim } 392218885Sdim return result; 393218885Sdim#else 394218885Sdim if (ErrMsg) 395218885Sdim *ErrMsg = "Program::Wait is not implemented on this platform yet!"; 396218885Sdim return -1; 397218885Sdim#endif 398218885Sdim} 399218885Sdim 400234353Sdimerror_code Program::ChangeStdinToBinary(){ 401218885Sdim // Do nothing, as Unix doesn't differentiate between text and binary. 402234353Sdim return make_error_code(errc::success); 403218885Sdim} 404218885Sdim 405234353Sdimerror_code Program::ChangeStdoutToBinary(){ 406218885Sdim // Do nothing, as Unix doesn't differentiate between text and binary. 407234353Sdim return make_error_code(errc::success); 408218885Sdim} 409218885Sdim 410234353Sdimerror_code Program::ChangeStderrToBinary(){ 411218885Sdim // Do nothing, as Unix doesn't differentiate between text and binary. 412234353Sdim return make_error_code(errc::success); 413218885Sdim} 414218885Sdim 415251662Sdimbool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { 416251662Sdim static long ArgMax = sysconf(_SC_ARG_MAX); 417251662Sdim 418251662Sdim // System says no practical limit. 419251662Sdim if (ArgMax == -1) 420251662Sdim return true; 421251662Sdim 422251662Sdim // Conservatively account for space required by environment variables. 423251662Sdim ArgMax /= 2; 424251662Sdim 425251662Sdim size_t ArgLength = 0; 426251662Sdim for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); 427251662Sdim I != E; ++I) { 428251662Sdim ArgLength += strlen(*I) + 1; 429251662Sdim if (ArgLength > size_t(ArgMax)) { 430251662Sdim return false; 431251662Sdim } 432251662Sdim } 433251662Sdim return true; 434218885Sdim} 435251662Sdim 436251662Sdim} 437