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