LLVM  11.0.0git
Program.inc
Go to the documentation of this file.
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"
24 #include "llvm/Support/Path.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 
62 namespace llvm {
63 
64 using namespace sys;
65 
66 ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
67 
68 ErrorOr<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  }
93 }
94 
95 static 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
124 static 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 
143 static void TimeOutHandler(int Sig) {
144 }
145 
146 static 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 
166 static std::vector<const char *>
167 toNullTerminatedCStringArray(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 
175 static 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 
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 
332 namespace llvm {
333 
334 ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
335  bool WaitUntilTerminates, std::string *ErrMsg) {
336  struct sigaction Act, Old;
337  assert(PI.Pid && "invalid pid to wait on, process not started?");
338 
339  int WaitPidOptions = 0;
340  pid_t ChildPid = PI.Pid;
341  if (WaitUntilTerminates) {
342  SecondsToWait = 0;
343  } else if (SecondsToWait) {
344  // Install a timeout handler. The handler itself does nothing, but the
345  // simple fact of having a handler at all causes the wait below to return
346  // with EINTR, unlike if we used SIG_IGN.
347  memset(&Act, 0, sizeof(Act));
348  Act.sa_handler = TimeOutHandler;
349  sigemptyset(&Act.sa_mask);
350  sigaction(SIGALRM, &Act, &Old);
351  alarm(SecondsToWait);
352  } else if (SecondsToWait == 0)
353  WaitPidOptions = WNOHANG;
354 
355  // Parent process: Wait for the child process to terminate.
356  int status;
357  ProcessInfo WaitResult;
358 
359  do {
360  WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
361  } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
362 
363  if (WaitResult.Pid != PI.Pid) {
364  if (WaitResult.Pid == 0) {
365  // Non-blocking wait.
366  return WaitResult;
367  } else {
368  if (SecondsToWait && errno == EINTR) {
369  // Kill the child.
370  kill(PI.Pid, SIGKILL);
371 
372  // Turn off the alarm and restore the signal handler
373  alarm(0);
374  sigaction(SIGALRM, &Old, nullptr);
375 
376  // Wait for child to die
377  if (wait(&status) != ChildPid)
378  MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
379  else
380  MakeErrMsg(ErrMsg, "Child timed out", 0);
381 
382  WaitResult.ReturnCode = -2; // Timeout detected
383  return WaitResult;
384  } else if (errno != EINTR) {
385  MakeErrMsg(ErrMsg, "Error waiting for child process");
386  WaitResult.ReturnCode = -1;
387  return WaitResult;
388  }
389  }
390  }
391 
392  // We exited normally without timeout, so turn off the timer.
393  if (SecondsToWait && !WaitUntilTerminates) {
394  alarm(0);
395  sigaction(SIGALRM, &Old, nullptr);
396  }
397 
398  // Return the proper exit status. Detect error conditions
399  // so we can return -1 for them and set ErrMsg informatively.
400  int result = 0;
401  if (WIFEXITED(status)) {
402  result = WEXITSTATUS(status);
403  WaitResult.ReturnCode = result;
404 
405  if (result == 127) {
406  if (ErrMsg)
407  *ErrMsg = llvm::sys::StrError(ENOENT);
408  WaitResult.ReturnCode = -1;
409  return WaitResult;
410  }
411  if (result == 126) {
412  if (ErrMsg)
413  *ErrMsg = "Program could not be executed";
414  WaitResult.ReturnCode = -1;
415  return WaitResult;
416  }
417  } else if (WIFSIGNALED(status)) {
418  if (ErrMsg) {
419  *ErrMsg = strsignal(WTERMSIG(status));
420 #ifdef WCOREDUMP
421  if (WCOREDUMP(status))
422  *ErrMsg += " (core dumped)";
423 #endif
424  }
425  // Return a special value to indicate that the process received an unhandled
426  // signal during execution as opposed to failing to execute.
427  WaitResult.ReturnCode = -2;
428  }
429  return WaitResult;
430 }
431 
432 std::error_code sys::ChangeStdinToBinary() {
433  // Do nothing, as Unix doesn't differentiate between text and binary.
434  return std::error_code();
435 }
436 
437 std::error_code sys::ChangeStdoutToBinary() {
438  // Do nothing, as Unix doesn't differentiate between text and binary.
439  return std::error_code();
440 }
441 
442 std::error_code
443 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
444  WindowsEncodingMethod Encoding /*unused*/) {
445  std::error_code EC;
447 
448  if (EC)
449  return EC;
450 
451  OS << Contents;
452 
453  if (OS.has_error())
455 
456  return EC;
457 }
458 
459 bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
460  ArrayRef<StringRef> Args) {
461  static long ArgMax = sysconf(_SC_ARG_MAX);
462  // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
463  // value for ARG_MAX on a POSIX compliant system.
464  static long ArgMin = _POSIX_ARG_MAX;
465 
466  // This the same baseline used by xargs.
467  long EffectiveArgMax = 128 * 1024;
468 
469  if (EffectiveArgMax > ArgMax)
470  EffectiveArgMax = ArgMax;
471  else if (EffectiveArgMax < ArgMin)
472  EffectiveArgMax = ArgMin;
473 
474  // System says no practical limit.
475  if (ArgMax == -1)
476  return true;
477 
478  // Conservatively account for space required by environment variables.
479  long HalfArgMax = EffectiveArgMax / 2;
480 
481  size_t ArgLength = Program.size() + 1;
482  for (StringRef Arg : Args) {
483  // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
484  // does not have a constant unlike what the man pages would have you
485  // believe. Since this limit is pretty high, perform the check
486  // unconditionally rather than trying to be aggressive and limiting it to
487  // Linux only.
488  if (Arg.size() >= (32 * 4096))
489  return false;
490 
491  ArgLength += Arg.size() + 1;
492  if (ArgLength > size_t(HalfArgMax)) {
493  return false;
494  }
495  }
496 
497  return true;
498 }
499 }
bool can_execute(const Twine &Path)
Can we execute this file?
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
std::error_code ChangeStdoutToBinary()
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:455
std::string StrError()
Returns a string representation of the errno value, using whatever thread-safe variant of strerror() ...
Definition: Errno.cpp:31
std::error_code make_error_code(BitcodeError E)
static constexpr size_t npos
Definition: StringRef.h:59
void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \\\)
SplitString - Split up the specified string according to the specified delimiters, appending the result fragments to the output list.
The file should be opened in text mode on platforms that make this distinction.
Definition: FileSystem.h:767
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition: Allocator.h:370
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
Instrumentation for Order File
bool commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef< StringRef > Args)
Return true if the given arguments fit within system-specific argument length limits.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Basic Register Allocator
std::error_code writeFileWithEncoding(StringRef FileName, StringRef Contents, WindowsEncodingMethod Encoding=WEM_UTF8)
Saves the UTF8-encoded contents string into the file FileName using a specific encoding.
auto size(R &&Range, std::enable_if_t< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1465
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix)
WindowsEncodingMethod
File encoding options when writing contents that a non-UTF8 tool will read (on Windows systems)...
Definition: Program.h:145
std::error_code ChangeStdinToBinary()
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:397
#define I(x, y, z)
Definition: MD5.cpp:59
static bool Execute(ProcessInfo &PI, StringRef Program, ArrayRef< StringRef > Args, Optional< ArrayRef< StringRef >> Env, ArrayRef< Optional< StringRef >> Redirects, unsigned MemoryLimit, std::string *ErrMsg)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ProcessInfo Wait(const ProcessInfo &PI, unsigned SecondsToWait, bool WaitUntilTerminates, std::string *ErrMsg=nullptr)
This function waits for the process specified by PI to finish.
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1063
constexpr char Args[]
Key for Kernel::Metadata::mArgs.