Program.inc revision 9f1d9fd1964d82f3e801efb71518144492cdf290
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 47namespace llvm { 48using namespace sys; 49 50// This function just uses the PATH environment variable to find the program. 51Path 52sys::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 // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb 168 // of virtual memory for shadow memory mapping. 169#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD 170 // Virtual memory. 171 getrlimit (RLIMIT_AS, &r); 172 r.rlim_cur = limit; 173 setrlimit (RLIMIT_AS, &r); 174#endif 175#endif 176#endif 177} 178 179} 180 181static bool Execute(void *&Data, const Path &path, const char **args, 182 const char **envp, const Path **redirects, 183 unsigned memoryLimit, std::string *ErrMsg) { 184 // If this OS has posix_spawn and there is no memory limit being implied, use 185 // posix_spawn. It is more efficient than fork/exec. 186#ifdef HAVE_POSIX_SPAWN 187 if (memoryLimit == 0) { 188 posix_spawn_file_actions_t FileActionsStore; 189 posix_spawn_file_actions_t *FileActions = 0; 190 191 if (redirects) { 192 FileActions = &FileActionsStore; 193 posix_spawn_file_actions_init(FileActions); 194 195 // Redirect stdin/stdout. 196 if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || 197 RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) 198 return false; 199 if (redirects[1] == 0 || redirects[2] == 0 || 200 *redirects[1] != *redirects[2]) { 201 // Just redirect stderr 202 if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; 203 } else { 204 // If stdout and stderr should go to the same place, redirect stderr 205 // to the FD already open for stdout. 206 if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2)) 207 return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); 208 } 209 } 210 211 if (!envp) 212#if !defined(__APPLE__) 213 envp = const_cast<const char **>(environ); 214#else 215 // environ is missing in dylibs. 216 envp = const_cast<const char **>(*_NSGetEnviron()); 217#endif 218 219 // Explicitly initialized to prevent what appears to be a valgrind false 220 // positive. 221 pid_t PID = 0; 222 int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, 223 const_cast<char **>(args), const_cast<char **>(envp)); 224 225 if (FileActions) 226 posix_spawn_file_actions_destroy(FileActions); 227 228 if (Err) 229 return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); 230 231 Data = reinterpret_cast<void*>(PID); 232 return true; 233 } 234#endif 235 236 // Create a child process. 237 int child = fork(); 238 switch (child) { 239 // An error occurred: Return to the caller. 240 case -1: 241 MakeErrMsg(ErrMsg, "Couldn't fork"); 242 return false; 243 244 // Child process: Execute the program. 245 case 0: { 246 // Redirect file descriptors... 247 if (redirects) { 248 // Redirect stdin 249 if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } 250 // Redirect stdout 251 if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } 252 if (redirects[1] && redirects[2] && 253 *(redirects[1]) == *(redirects[2])) { 254 // If stdout and stderr should go to the same place, redirect stderr 255 // to the FD already open for stdout. 256 if (-1 == dup2(1,2)) { 257 MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); 258 return false; 259 } 260 } else { 261 // Just redirect stderr 262 if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } 263 } 264 } 265 266 // Set memory limits 267 if (memoryLimit!=0) { 268 SetMemoryLimits(memoryLimit); 269 } 270 271 // Execute! 272 if (envp != 0) 273 execve(path.c_str(), 274 const_cast<char **>(args), 275 const_cast<char **>(envp)); 276 else 277 execv(path.c_str(), 278 const_cast<char **>(args)); 279 // If the execve() failed, we should exit. Follow Unix protocol and 280 // return 127 if the executable was not found, and 126 otherwise. 281 // Use _exit rather than exit so that atexit functions and static 282 // object destructors cloned from the parent process aren't 283 // redundantly run, and so that any data buffered in stdio buffers 284 // cloned from the parent aren't redundantly written out. 285 _exit(errno == ENOENT ? 127 : 126); 286 } 287 288 // Parent process: Break out of the switch to do our processing. 289 default: 290 break; 291 } 292 293 Data = reinterpret_cast<void*>(child); 294 295 return true; 296} 297 298static int Wait(void *&Data, const sys::Path &path, unsigned secondsToWait, 299 std::string *ErrMsg) { 300#ifdef HAVE_SYS_WAIT_H 301 struct sigaction Act, Old; 302 303 if (Data == 0) { 304 MakeErrMsg(ErrMsg, "Process not started!"); 305 return -1; 306 } 307 308 // Install a timeout handler. The handler itself does nothing, but the simple 309 // fact of having a handler at all causes the wait below to return with EINTR, 310 // unlike if we used SIG_IGN. 311 if (secondsToWait) { 312 memset(&Act, 0, sizeof(Act)); 313 Act.sa_handler = TimeOutHandler; 314 sigemptyset(&Act.sa_mask); 315 sigaction(SIGALRM, &Act, &Old); 316 alarm(secondsToWait); 317 } 318 319 // Parent process: Wait for the child process to terminate. 320 int status; 321 uint64_t pid = reinterpret_cast<uint64_t>(Data); 322 pid_t child = static_cast<pid_t>(pid); 323 while (waitpid(pid, &status, 0) != child) 324 if (secondsToWait && errno == EINTR) { 325 // Kill the child. 326 kill(child, SIGKILL); 327 328 // Turn off the alarm and restore the signal handler 329 alarm(0); 330 sigaction(SIGALRM, &Old, 0); 331 332 // Wait for child to die 333 if (wait(&status) != child) 334 MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); 335 else 336 MakeErrMsg(ErrMsg, "Child timed out", 0); 337 338 return -2; // Timeout detected 339 } else if (errno != EINTR) { 340 MakeErrMsg(ErrMsg, "Error waiting for child process"); 341 return -1; 342 } 343 344 // We exited normally without timeout, so turn off the timer. 345 if (secondsToWait) { 346 alarm(0); 347 sigaction(SIGALRM, &Old, 0); 348 } 349 350 // Return the proper exit status. Detect error conditions 351 // so we can return -1 for them and set ErrMsg informatively. 352 int result = 0; 353 if (WIFEXITED(status)) { 354 result = WEXITSTATUS(status); 355#ifdef HAVE_POSIX_SPAWN 356 // The posix_spawn child process returns 127 on any kind of error. 357 // Following the POSIX convention for command-line tools (which posix_spawn 358 // itself apparently does not), check to see if the failure was due to some 359 // reason other than the file not existing, and return 126 in this case. 360 bool Exists; 361 if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) 362 result = 126; 363#endif 364 if (result == 127) { 365 if (ErrMsg) 366 *ErrMsg = llvm::sys::StrError(ENOENT); 367 return -1; 368 } 369 if (result == 126) { 370 if (ErrMsg) 371 *ErrMsg = "Program could not be executed"; 372 return -1; 373 } 374 } else if (WIFSIGNALED(status)) { 375 if (ErrMsg) { 376 *ErrMsg = strsignal(WTERMSIG(status)); 377#ifdef WCOREDUMP 378 if (WCOREDUMP(status)) 379 *ErrMsg += " (core dumped)"; 380#endif 381 } 382 // Return a special value to indicate that the process received an unhandled 383 // signal during execution as opposed to failing to execute. 384 return -2; 385 } 386 return result; 387#else 388 if (ErrMsg) 389 *ErrMsg = "Program::Wait is not implemented on this platform yet!"; 390 return -1; 391#endif 392} 393 394namespace llvm { 395 396error_code sys::ChangeStdinToBinary(){ 397 // Do nothing, as Unix doesn't differentiate between text and binary. 398 return make_error_code(errc::success); 399} 400 401error_code sys::ChangeStdoutToBinary(){ 402 // Do nothing, as Unix doesn't differentiate between text and binary. 403 return make_error_code(errc::success); 404} 405 406error_code sys::ChangeStderrToBinary(){ 407 // Do nothing, as Unix doesn't differentiate between text and binary. 408 return make_error_code(errc::success); 409} 410 411bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { 412 static long ArgMax = sysconf(_SC_ARG_MAX); 413 414 // System says no practical limit. 415 if (ArgMax == -1) 416 return true; 417 418 // Conservatively account for space required by environment variables. 419 ArgMax /= 2; 420 421 size_t ArgLength = 0; 422 for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); 423 I != E; ++I) { 424 ArgLength += strlen(*I) + 1; 425 if (ArgLength > size_t(ArgMax)) { 426 return false; 427 } 428 } 429 return true; 430} 431 432} 433