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