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