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