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