Program.inc revision 234353
1213365Smarcel//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// 2214006Smarcel// 3213365Smarcel// The LLVM Compiler Infrastructure 4213365Smarcel// 5213365Smarcel// This file is distributed under the University of Illinois Open Source 6213365Smarcel// License. See LICENSE.TXT for details. 7213365Smarcel// 8213365Smarcel//===----------------------------------------------------------------------===// 9213365Smarcel// 10213365Smarcel// This file implements the Unix specific portion of the Program class. 11213365Smarcel// 12213365Smarcel//===----------------------------------------------------------------------===// 13213365Smarcel 14213365Smarcel//===----------------------------------------------------------------------===// 15213365Smarcel//=== WARNING: Implementation here must contain only generic UNIX code that 16213365Smarcel//=== is guaranteed to work on *all* UNIX variants. 17213365Smarcel//===----------------------------------------------------------------------===// 18213365Smarcel 19213365Smarcel#include <llvm/Config/config.h> 20213365Smarcel#include "llvm/Support/FileSystem.h" 21213365Smarcel#include "Unix.h" 22213365Smarcel#if HAVE_SYS_STAT_H 23213365Smarcel#include <sys/stat.h> 24213365Smarcel#endif 25213365Smarcel#if HAVE_SYS_RESOURCE_H 26213365Smarcel#include <sys/resource.h> 27213365Smarcel#endif 28213365Smarcel#if HAVE_SIGNAL_H 29213365Smarcel#include <signal.h> 30213365Smarcel#endif 31213365Smarcel#if HAVE_FCNTL_H 32213365Smarcel#include <fcntl.h> 33213365Smarcel#endif 34213365Smarcel#ifdef HAVE_POSIX_SPAWN 35213365Smarcel#include <spawn.h> 36213365Smarcel#if !defined(__APPLE__) 37213365Smarcel extern char **environ; 38214006Smarcel#else 39214006Smarcel#include <crt_externs.h> // _NSGetEnviron 40213365Smarcel#endif 41213365Smarcel#endif 42213365Smarcel 43213365Smarcelnamespace llvm { 44213365Smarcelusing namespace sys; 45228634Savg 46213365SmarcelProgram::Program() : Data_(0) {} 47213365Smarcel 48213365SmarcelProgram::~Program() {} 49213365Smarcel 50214006Smarcelunsigned Program::GetPid() const { 51213365Smarcel uint64_t pid = reinterpret_cast<uint64_t>(Data_); 52213365Smarcel return static_cast<unsigned>(pid); 53213365Smarcel} 54213365Smarcel 55213365Smarcel// This function just uses the PATH environment variable to find the program. 56213365SmarcelPath 57213365SmarcelProgram::FindProgramByName(const std::string& progName) { 58223919Sae 59214006Smarcel // Check some degenerate cases 60213365Smarcel if (progName.length() == 0) // no program 61213365Smarcel return Path(); 62213365Smarcel Path temp; 63213365Smarcel if (!temp.set(progName)) // invalid name 64213365Smarcel return Path(); 65213365Smarcel // Use the given path verbatim if it contains any slashes; this matches 66213365Smarcel // the behavior of sh(1) and friends. 67213365Smarcel if (progName.find('/') != std::string::npos) 68213365Smarcel return temp; 69213365Smarcel 70213365Smarcel // At this point, the file name is valid and does not contain slashes. Search 71213365Smarcel // for it through the directories specified in the PATH environment variable. 72213365Smarcel 73213365Smarcel // Get the path. If its empty, we can't do anything to find it. 74213365Smarcel const char *PathStr = getenv("PATH"); 75213365Smarcel if (PathStr == 0) 76213365Smarcel return Path(); 77213365Smarcel 78213365Smarcel // Now we have a colon separated list of directories to search; try them. 79213365Smarcel size_t PathLen = strlen(PathStr); 80213365Smarcel while (PathLen) { 81213365Smarcel // Find the first colon... 82213365Smarcel const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); 83213365Smarcel 84213365Smarcel // Check to see if this first directory contains the executable... 85213365Smarcel Path FilePath; 86213365Smarcel if (FilePath.set(std::string(PathStr,Colon))) { 87213365Smarcel FilePath.appendComponent(progName); 88213365Smarcel if (FilePath.canExecute()) 89214006Smarcel return FilePath; // Found the executable! 90214006Smarcel } 91214006Smarcel 92213365Smarcel // Nope it wasn't in this directory, check the next path in the list! 93214006Smarcel PathLen -= Colon-PathStr; 94214006Smarcel PathStr = Colon; 95213365Smarcel 96214006Smarcel // Advance past duplicate colons 97213365Smarcel while (*PathStr == ':') { 98214006Smarcel PathStr++; 99213365Smarcel PathLen--; 100213365Smarcel } 101213365Smarcel } 102213365Smarcel return Path(); 103213365Smarcel} 104213365Smarcel 105213365Smarcelstatic bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { 106213365Smarcel if (Path == 0) // Noop 107213365Smarcel return false; 108214006Smarcel const char *File; 109214006Smarcel if (Path->isEmpty()) 110214006Smarcel // Redirect empty paths to /dev/null 111214006Smarcel File = "/dev/null"; 112214006Smarcel else 113214006Smarcel File = Path->c_str(); 114214006Smarcel 115214006Smarcel // Open the file 116214006Smarcel int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); 117214006Smarcel if (InFD == -1) { 118213365Smarcel MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for " 119213365Smarcel + (FD == 0 ? "input" : "output")); 120214006Smarcel return true; 121214006Smarcel } 122253910Smarcel 123214006Smarcel // Install it as the requested FD 124213365Smarcel if (dup2(InFD, FD) == -1) { 125213365Smarcel MakeErrMsg(ErrMsg, "Cannot dup2"); 126213365Smarcel close(InFD); 127213365Smarcel return true; 128213365Smarcel } 129213365Smarcel close(InFD); // Close the original FD 130213365Smarcel return false; 131213365Smarcel} 132213365Smarcel 133213365Smarcel#ifdef HAVE_POSIX_SPAWN 134213365Smarcelstatic bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, 135213365Smarcel posix_spawn_file_actions_t *FileActions) { 136213365Smarcel if (Path == 0) // Noop 137213365Smarcel return false; 138213365Smarcel const char *File; 139213365Smarcel if (Path->isEmpty()) 140213365Smarcel // Redirect empty paths to /dev/null 141213365Smarcel File = "/dev/null"; 142213365Smarcel else 143213365Smarcel File = Path->c_str(); 144213365Smarcel 145213365Smarcel if (int Err = posix_spawn_file_actions_addopen(FileActions, FD, 146213365Smarcel File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) 147213365Smarcel return MakeErrMsg(ErrMsg, "Cannot dup2", Err); 148213365Smarcel return false; 149213365Smarcel} 150213365Smarcel#endif 151213365Smarcel 152213365Smarcelstatic void TimeOutHandler(int Sig) { 153213365Smarcel} 154213365Smarcel 155213365Smarcelstatic void SetMemoryLimits (unsigned size) 156213365Smarcel{ 157213365Smarcel#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT 158213365Smarcel struct rlimit r; 159213365Smarcel __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; 160213365Smarcel 161213365Smarcel // Heap size 162213365Smarcel getrlimit (RLIMIT_DATA, &r); 163213365Smarcel r.rlim_cur = limit; 164213365Smarcel setrlimit (RLIMIT_DATA, &r); 165213365Smarcel#ifdef RLIMIT_RSS 166213365Smarcel // Resident set size. 167213365Smarcel getrlimit (RLIMIT_RSS, &r); 168213365Smarcel r.rlim_cur = limit; 169213365Smarcel setrlimit (RLIMIT_RSS, &r); 170213365Smarcel#endif 171213365Smarcel#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. 172213365Smarcel // Virtual memory. 173213365Smarcel getrlimit (RLIMIT_AS, &r); 174213365Smarcel r.rlim_cur = limit; 175213365Smarcel setrlimit (RLIMIT_AS, &r); 176213365Smarcel#endif 177213365Smarcel#endif 178213365Smarcel} 179213365Smarcel 180213365Smarcelbool 181213365SmarcelProgram::Execute(const Path &path, const char **args, const char **envp, 182213365Smarcel const Path **redirects, unsigned memoryLimit, 183213365Smarcel std::string *ErrMsg) { 184213365Smarcel // If this OS has posix_spawn and there is no memory limit being implied, use 185213365Smarcel // posix_spawn. It is more efficient than fork/exec. 186213365Smarcel#ifdef HAVE_POSIX_SPAWN 187213365Smarcel if (memoryLimit == 0) { 188213365Smarcel posix_spawn_file_actions_t FileActionsStore; 189213365Smarcel posix_spawn_file_actions_t *FileActions = 0; 190213365Smarcel 191213365Smarcel if (redirects) { 192213365Smarcel FileActions = &FileActionsStore; 193213365Smarcel posix_spawn_file_actions_init(FileActions); 194213365Smarcel 195213365Smarcel // Redirect stdin/stdout. 196213365Smarcel if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || 197213365Smarcel RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) 198213365Smarcel return false; 199213365Smarcel if (redirects[1] == 0 || redirects[2] == 0 || 200213365Smarcel *redirects[1] != *redirects[2]) { 201213365Smarcel // Just redirect stderr 202213365Smarcel if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; 203213365Smarcel } else { 204213365Smarcel // If stdout and stderr should go to the same place, redirect stderr 205214006Smarcel // to the FD already open for stdout. 206214006Smarcel if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2)) 207213365Smarcel return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); 208213365Smarcel } 209213365Smarcel } 210214006Smarcel 211213365Smarcel if (!envp) 212213365Smarcel#if !defined(__APPLE__) 213214006Smarcel envp = const_cast<const char **>(environ); 214214006Smarcel#else 215213365Smarcel // environ is missing in dylibs. 216213365Smarcel envp = const_cast<const char **>(*_NSGetEnviron()); 217213365Smarcel#endif 218214006Smarcel 219213365Smarcel // Explicitly initialized to prevent what appears to be a valgrind false 220213365Smarcel // positive. 221213365Smarcel pid_t PID = 0; 222213365Smarcel int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, 223213365Smarcel const_cast<char **>(args), const_cast<char **>(envp)); 224213365Smarcel 225214006Smarcel if (FileActions) 226213365Smarcel posix_spawn_file_actions_destroy(FileActions); 227213365Smarcel 228213365Smarcel if (Err) 229213365Smarcel return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); 230213365Smarcel 231213365Smarcel Data_ = reinterpret_cast<void*>(PID); 232213365Smarcel return true; 233213365Smarcel } 234213365Smarcel#endif 235214006Smarcel 236213365Smarcel // Create a child process. 237213365Smarcel int child = fork(); 238213365Smarcel switch (child) { 239213365Smarcel // An error occurred: Return to the caller. 240213365Smarcel case -1: 241214006Smarcel MakeErrMsg(ErrMsg, "Couldn't fork"); 242214006Smarcel return false; 243213365Smarcel 244213365Smarcel // Child process: Execute the program. 245214006Smarcel case 0: { 246214006Smarcel // Redirect file descriptors... 247213365Smarcel if (redirects) { 248213365Smarcel // Redirect stdin 249214006Smarcel if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } 250214006Smarcel // Redirect stdout 251214006Smarcel if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } 252213365Smarcel if (redirects[1] && redirects[2] && 253213365Smarcel *(redirects[1]) == *(redirects[2])) { 254214006Smarcel // If stdout and stderr should go to the same place, redirect stderr 255214006Smarcel // to the FD already open for stdout. 256214006Smarcel if (-1 == dup2(1,2)) { 257213365Smarcel MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); 258214006Smarcel return false; 259214006Smarcel } 260214006Smarcel } else { 261214006Smarcel // Just redirect stderr 262214006Smarcel if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } 263214006Smarcel } 264214006Smarcel } 265213365Smarcel 266213365Smarcel // Set memory limits 267214006Smarcel if (memoryLimit!=0) { 268214006Smarcel SetMemoryLimits(memoryLimit); 269214006Smarcel } 270213365Smarcel 271214006Smarcel // Execute! 272214006Smarcel if (envp != 0) 273214006Smarcel execve(path.c_str(), 274214006Smarcel const_cast<char **>(args), 275214006Smarcel const_cast<char **>(envp)); 276214006Smarcel else 277214006Smarcel execv(path.c_str(), 278214006Smarcel const_cast<char **>(args)); 279214006Smarcel // If the execve() failed, we should exit. Follow Unix protocol and 280214006Smarcel // return 127 if the executable was not found, and 126 otherwise. 281214006Smarcel // Use _exit rather than exit so that atexit functions and static 282214006Smarcel // object destructors cloned from the parent process aren't 283213365Smarcel // redundantly run, and so that any data buffered in stdio buffers 284213365Smarcel // cloned from the parent aren't redundantly written out. 285213365Smarcel _exit(errno == ENOENT ? 127 : 126); 286214006Smarcel } 287214006Smarcel 288214006Smarcel // Parent process: Break out of the switch to do our processing. 289214006Smarcel default: 290214006Smarcel break; 291214006Smarcel } 292214006Smarcel 293214006Smarcel Data_ = reinterpret_cast<void*>(child); 294214006Smarcel 295214006Smarcel return true; 296214006Smarcel} 297214006Smarcel 298214006Smarcelint 299214006SmarcelProgram::Wait(const sys::Path &path, 300214006Smarcel unsigned secondsToWait, 301214006Smarcel std::string* ErrMsg) 302214006Smarcel{ 303214006Smarcel#ifdef HAVE_SYS_WAIT_H 304214006Smarcel struct sigaction Act, Old; 305214006Smarcel 306214006Smarcel if (Data_ == 0) { 307214006Smarcel MakeErrMsg(ErrMsg, "Process not started!"); 308214006Smarcel return -1; 309214006Smarcel } 310214006Smarcel 311214006Smarcel // Install a timeout handler. The handler itself does nothing, but the simple 312214006Smarcel // fact of having a handler at all causes the wait below to return with EINTR, 313214006Smarcel // unlike if we used SIG_IGN. 314214006Smarcel if (secondsToWait) { 315214006Smarcel memset(&Act, 0, sizeof(Act)); 316214006Smarcel Act.sa_handler = TimeOutHandler; 317214006Smarcel sigemptyset(&Act.sa_mask); 318214006Smarcel sigaction(SIGALRM, &Act, &Old); 319214006Smarcel alarm(secondsToWait); 320214006Smarcel } 321214006Smarcel 322213365Smarcel // Parent process: Wait for the child process to terminate. 323213365Smarcel int status; 324214006Smarcel uint64_t pid = reinterpret_cast<uint64_t>(Data_); 325214006Smarcel pid_t child = static_cast<pid_t>(pid); 326214006Smarcel while (waitpid(pid, &status, 0) != child) 327214006Smarcel if (secondsToWait && errno == EINTR) { 328214006Smarcel // Kill the child. 329214006Smarcel kill(child, SIGKILL); 330214006Smarcel 331214006Smarcel // Turn off the alarm and restore the signal handler 332214006Smarcel alarm(0); 333214006Smarcel sigaction(SIGALRM, &Old, 0); 334214006Smarcel 335214006Smarcel // Wait for child to die 336214006Smarcel if (wait(&status) != child) 337214006Smarcel MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); 338214006Smarcel else 339214006Smarcel MakeErrMsg(ErrMsg, "Child timed out", 0); 340214006Smarcel 341213365Smarcel return -2; // Timeout detected 342214006Smarcel } else if (errno != EINTR) { 343214006Smarcel MakeErrMsg(ErrMsg, "Error waiting for child process"); 344214006Smarcel return -1; 345213365Smarcel } 346214006Smarcel 347214006Smarcel // We exited normally without timeout, so turn off the timer. 348214006Smarcel if (secondsToWait) { 349214006Smarcel alarm(0); 350214006Smarcel sigaction(SIGALRM, &Old, 0); 351214006Smarcel } 352214006Smarcel 353214006Smarcel // Return the proper exit status. Detect error conditions 354213365Smarcel // so we can return -1 for them and set ErrMsg informatively. 355214006Smarcel int result = 0; 356214006Smarcel if (WIFEXITED(status)) { 357214006Smarcel result = WEXITSTATUS(status); 358214006Smarcel#ifdef HAVE_POSIX_SPAWN 359214006Smarcel // The posix_spawn child process returns 127 on any kind of error. 360214006Smarcel // Following the POSIX convention for command-line tools (which posix_spawn 361214006Smarcel // itself apparently does not), check to see if the failure was due to some 362214006Smarcel // reason other than the file not existing, and return 126 in this case. 363214006Smarcel bool Exists; 364214006Smarcel if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) 365214006Smarcel result = 126; 366214006Smarcel#endif 367214006Smarcel if (result == 127) { 368214006Smarcel if (ErrMsg) 369214006Smarcel *ErrMsg = llvm::sys::StrError(ENOENT); 370214006Smarcel return -1; 371214006Smarcel } 372214006Smarcel if (result == 126) { 373214006Smarcel if (ErrMsg) 374214006Smarcel *ErrMsg = "Program could not be executed"; 375214006Smarcel return -1; 376214006Smarcel } 377214006Smarcel } else if (WIFSIGNALED(status)) { 378214006Smarcel if (ErrMsg) { 379214006Smarcel *ErrMsg = strsignal(WTERMSIG(status)); 380214006Smarcel#ifdef WCOREDUMP 381214006Smarcel if (WCOREDUMP(status)) 382214006Smarcel *ErrMsg += " (core dumped)"; 383214006Smarcel#endif 384214006Smarcel } 385214006Smarcel // Return a special value to indicate that the process received an unhandled 386214006Smarcel // signal during execution as opposed to failing to execute. 387214006Smarcel return -2; 388214006Smarcel } 389214006Smarcel return result; 390214006Smarcel#else 391214006Smarcel if (ErrMsg) 392214006Smarcel *ErrMsg = "Program::Wait is not implemented on this platform yet!"; 393214006Smarcel return -1; 394214006Smarcel#endif 395214006Smarcel} 396214006Smarcel 397214006Smarcelbool 398214006SmarcelProgram::Kill(std::string* ErrMsg) { 399214006Smarcel if (Data_ == 0) { 400214006Smarcel MakeErrMsg(ErrMsg, "Process not started!"); 401214006Smarcel return true; 402214006Smarcel } 403214006Smarcel 404214006Smarcel uint64_t pid64 = reinterpret_cast<uint64_t>(Data_); 405214006Smarcel pid_t pid = static_cast<pid_t>(pid64); 406214006Smarcel 407214006Smarcel if (kill(pid, SIGKILL) != 0) { 408214006Smarcel MakeErrMsg(ErrMsg, "The process couldn't be killed!"); 409214006Smarcel return true; 410214006Smarcel } 411214006Smarcel 412214006Smarcel return false; 413214006Smarcel} 414214006Smarcel 415214006Smarcelerror_code Program::ChangeStdinToBinary(){ 416214006Smarcel // Do nothing, as Unix doesn't differentiate between text and binary. 417214006Smarcel return make_error_code(errc::success); 418214006Smarcel} 419214006Smarcel 420214006Smarcelerror_code Program::ChangeStdoutToBinary(){ 421214006Smarcel // Do nothing, as Unix doesn't differentiate between text and binary. 422214006Smarcel return make_error_code(errc::success); 423214006Smarcel} 424213365Smarcel 425214006Smarcelerror_code Program::ChangeStderrToBinary(){ 426214006Smarcel // Do nothing, as Unix doesn't differentiate between text and binary. 427213365Smarcel return make_error_code(errc::success); 428214006Smarcel} 429214006Smarcel 430214006Smarcel} 431214006Smarcel