LLVM  10.0.0svn
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)
74  return std::string(Name);
75 
76  SmallVector<StringRef, 16> EnvironmentPaths;
77  if (Paths.empty())
78  if (const char *PathEnv = std::getenv("PATH")) {
79  SplitString(PathEnv, EnvironmentPaths, ":");
80  Paths = EnvironmentPaths;
81  }
82 
83  for (auto Path : Paths) {
84  if (Path.empty())
85  continue;
86 
87  // Check to see if this first directory contains the executable...
88  SmallString<128> FilePath(Path);
89  sys::path::append(FilePath, Name);
90  if (sys::fs::can_execute(FilePath.c_str()))
91  return std::string(FilePath.str()); // Found the executable!
92  }
94 }
95 
96 static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
97  if (!Path) // 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
125 static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
126  posix_spawn_file_actions_t *FileActions) {
127  if (!Path) // 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 posix_spawn_file_actions_addopen", Err);
140  return false;
141 }
142 #endif
143 
144 static void TimeOutHandler(int Sig) {
145 }
146 
147 static void SetMemoryLimits(unsigned size) {
148 #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
149  struct rlimit r;
150  __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
151 
152  // Heap size
153  getrlimit (RLIMIT_DATA, &r);
154  r.rlim_cur = limit;
155  setrlimit (RLIMIT_DATA, &r);
156 #ifdef RLIMIT_RSS
157  // Resident set size.
158  getrlimit (RLIMIT_RSS, &r);
159  r.rlim_cur = limit;
160  setrlimit (RLIMIT_RSS, &r);
161 #endif
162 #endif
163 }
164 
165 }
166 
167 static std::vector<const char *>
168 toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
169  std::vector<const char *> Result;
170  for (StringRef S : Strings)
171  Result.push_back(Saver.save(S).data());
172  Result.push_back(nullptr);
173  return Result;
174 }
175 
176 static bool Execute(ProcessInfo &PI, StringRef Program,
177  ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
178  ArrayRef<Optional<StringRef>> Redirects,
179  unsigned MemoryLimit, std::string *ErrMsg) {
180  if (!llvm::sys::fs::exists(Program)) {
181  if (ErrMsg)
182  *ErrMsg = std::string("Executable \"") + Program.str() +
183  std::string("\" doesn't exist!");
184  return false;
185  }
186 
188  StringSaver Saver(Allocator);
189  std::vector<const char *> ArgVector, EnvVector;
190  const char **Argv = nullptr;
191  const char **Envp = nullptr;
192  ArgVector = toNullTerminatedCStringArray(Args, Saver);
193  Argv = ArgVector.data();
194  if (Env) {
195  EnvVector = toNullTerminatedCStringArray(*Env, Saver);
196  Envp = EnvVector.data();
197  }
198 
199  // If this OS has posix_spawn and there is no memory limit being implied, use
200  // posix_spawn. It is more efficient than fork/exec.
201 #ifdef HAVE_POSIX_SPAWN
202  if (MemoryLimit == 0) {
203  posix_spawn_file_actions_t FileActionsStore;
204  posix_spawn_file_actions_t *FileActions = nullptr;
205 
206  // If we call posix_spawn_file_actions_addopen we have to make sure the
207  // c strings we pass to it stay alive until the call to posix_spawn,
208  // so we copy any StringRefs into this variable.
209  std::string RedirectsStorage[3];
210 
211  if (!Redirects.empty()) {
212  assert(Redirects.size() == 3);
213  std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
214  for (int I = 0; I < 3; ++I) {
215  if (Redirects[I]) {
216  RedirectsStorage[I] = *Redirects[I];
217  RedirectsStr[I] = &RedirectsStorage[I];
218  }
219  }
220 
221  FileActions = &FileActionsStore;
222  posix_spawn_file_actions_init(FileActions);
223 
224  // Redirect stdin/stdout.
225  if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
226  RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
227  return false;
228  if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
229  // Just redirect stderr
230  if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
231  return false;
232  } else {
233  // If stdout and stderr should go to the same place, redirect stderr
234  // to the FD already open for stdout.
235  if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
236  return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
237  }
238  }
239 
240  if (!Envp)
241 #if !USE_NSGETENVIRON
242  Envp = const_cast<const char **>(environ);
243 #else
244  // environ is missing in dylibs.
245  Envp = const_cast<const char **>(*_NSGetEnviron());
246 #endif
247 
248  constexpr int maxRetries = 8;
249  int retries = 0;
250  pid_t PID;
251  int Err;
252  do {
253  PID = 0; // Make Valgrind happy.
254  Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
255  /*attrp*/ nullptr, const_cast<char **>(Argv),
256  const_cast<char **>(Envp));
257  } while (Err == EINTR && ++retries < maxRetries);
258 
259  if (FileActions)
260  posix_spawn_file_actions_destroy(FileActions);
261 
262  if (Err)
263  return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
264 
265  PI.Pid = PID;
266  PI.Process = PID;
267 
268  return true;
269  }
270 #endif
271 
272  // Create a child process.
273  int child = fork();
274  switch (child) {
275  // An error occurred: Return to the caller.
276  case -1:
277  MakeErrMsg(ErrMsg, "Couldn't fork");
278  return false;
279 
280  // Child process: Execute the program.
281  case 0: {
282  // Redirect file descriptors...
283  if (!Redirects.empty()) {
284  // Redirect stdin
285  if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
286  // Redirect stdout
287  if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
288  if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
289  // If stdout and stderr should go to the same place, redirect stderr
290  // to the FD already open for stdout.
291  if (-1 == dup2(1,2)) {
292  MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
293  return false;
294  }
295  } else {
296  // Just redirect stderr
297  if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
298  }
299  }
300 
301  // Set memory limits
302  if (MemoryLimit!=0) {
303  SetMemoryLimits(MemoryLimit);
304  }
305 
306  // Execute!
307  std::string PathStr = Program;
308  if (Envp != nullptr)
309  execve(PathStr.c_str(), const_cast<char **>(Argv),
310  const_cast<char **>(Envp));
311  else
312  execv(PathStr.c_str(), const_cast<char **>(Argv));
313  // If the execve() failed, we should exit. Follow Unix protocol and
314  // return 127 if the executable was not found, and 126 otherwise.
315  // Use _exit rather than exit so that atexit functions and static
316  // object destructors cloned from the parent process aren't
317  // redundantly run, and so that any data buffered in stdio buffers
318  // cloned from the parent aren't redundantly written out.
319  _exit(errno == ENOENT ? 127 : 126);
320  }
321 
322  // Parent process: Break out of the switch to do our processing.
323  default:
324  break;
325  }
326 
327  PI.Pid = child;
328  PI.Process = child;
329 
330  return true;
331 }
332 
333 namespace llvm {
334 
335 ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
336  bool WaitUntilTerminates, std::string *ErrMsg) {
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 
360  do {
361  WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
362  } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
363 
364  if (WaitResult.Pid != PI.Pid) {
365  if (WaitResult.Pid == 0) {
366  // Non-blocking wait.
367  return WaitResult;
368  } else {
369  if (SecondsToWait && errno == EINTR) {
370  // Kill the child.
371  kill(PI.Pid, SIGKILL);
372 
373  // Turn off the alarm and restore the signal handler
374  alarm(0);
375  sigaction(SIGALRM, &Old, nullptr);
376 
377  // Wait for child to die
378  if (wait(&status) != ChildPid)
379  MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
380  else
381  MakeErrMsg(ErrMsg, "Child timed out", 0);
382 
383  WaitResult.ReturnCode = -2; // Timeout detected
384  return WaitResult;
385  } else if (errno != EINTR) {
386  MakeErrMsg(ErrMsg, "Error waiting for child process");
387  WaitResult.ReturnCode = -1;
388  return WaitResult;
389  }
390  }
391  }
392 
393  // We exited normally without timeout, so turn off the timer.
394  if (SecondsToWait && !WaitUntilTerminates) {
395  alarm(0);
396  sigaction(SIGALRM, &Old, nullptr);
397  }
398 
399  // Return the proper exit status. Detect error conditions
400  // so we can return -1 for them and set ErrMsg informatively.
401  int result = 0;
402  if (WIFEXITED(status)) {
403  result = WEXITSTATUS(status);
404  WaitResult.ReturnCode = result;
405 
406  if (result == 127) {
407  if (ErrMsg)
408  *ErrMsg = llvm::sys::StrError(ENOENT);
409  WaitResult.ReturnCode = -1;
410  return WaitResult;
411  }
412  if (result == 126) {
413  if (ErrMsg)
414  *ErrMsg = "Program could not be executed";
415  WaitResult.ReturnCode = -1;
416  return WaitResult;
417  }
418  } else if (WIFSIGNALED(status)) {
419  if (ErrMsg) {
420  *ErrMsg = strsignal(WTERMSIG(status));
421 #ifdef WCOREDUMP
422  if (WCOREDUMP(status))
423  *ErrMsg += " (core dumped)";
424 #endif
425  }
426  // Return a special value to indicate that the process received an unhandled
427  // signal during execution as opposed to failing to execute.
428  WaitResult.ReturnCode = -2;
429  }
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 
443 std::error_code
444 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
445  WindowsEncodingMethod Encoding /*unused*/) {
446  std::error_code EC;
448 
449  if (EC)
450  return EC;
451 
452  OS << Contents;
453 
454  if (OS.has_error())
456 
457  return EC;
458 }
459 
460 bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
461  ArrayRef<StringRef> Args) {
462  static long ArgMax = sysconf(_SC_ARG_MAX);
463  // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
464  // value for ARG_MAX on a POSIX compliant system.
465  static long ArgMin = _POSIX_ARG_MAX;
466 
467  // This the same baseline used by xargs.
468  long EffectiveArgMax = 128 * 1024;
469 
470  if (EffectiveArgMax > ArgMax)
471  EffectiveArgMax = ArgMax;
472  else if (EffectiveArgMax < ArgMin)
473  EffectiveArgMax = ArgMin;
474 
475  // System says no practical limit.
476  if (ArgMax == -1)
477  return true;
478 
479  // Conservatively account for space required by environment variables.
480  long HalfArgMax = EffectiveArgMax / 2;
481 
482  size_t ArgLength = Program.size() + 1;
483  for (StringRef Arg : Args) {
484  // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
485  // does not have a constant unlike what the man pages would have you
486  // believe. Since this limit is pretty high, perform the check
487  // unconditionally rather than trying to be aggressive and limiting it to
488  // Linux only.
489  if (Arg.size() >= (32 * 4096))
490  return false;
491 
492  ArgLength += Arg.size() + 1;
493  if (ArgLength > size_t(HalfArgMax)) {
494  return false;
495  }
496  }
497 
498  return true;
499 }
500 }
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)
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:434
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
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1158
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.
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:384
static const size_t npos
Definition: StringRef.h:50
#define I(x, y, z)
Definition: MD5.cpp:58
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:1025
constexpr char Args[]
Key for Kernel::Metadata::mArgs.