• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Config/config.h"
22#include "llvm/Support/Compiler.h"
23#include "llvm/Support/Errc.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/Path.h"
26#include "llvm/Support/StringSaver.h"
27#include "llvm/Support/raw_ostream.h"
28#if HAVE_SYS_STAT_H
29#include <sys/stat.h>
30#endif
31#if HAVE_SYS_RESOURCE_H
32#include <sys/resource.h>
33#endif
34#if HAVE_SIGNAL_H
35#include <signal.h>
36#endif
37#if HAVE_FCNTL_H
38#include <fcntl.h>
39#endif
40#if HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#ifdef HAVE_POSIX_SPAWN
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 errc::no_such_file_or_directory;
95}
96
97static bool RedirectIO(Optional<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#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
150  struct rlimit r;
151  __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
152
153  // Heap size
154  getrlimit (RLIMIT_DATA, &r);
155  r.rlim_cur = limit;
156  setrlimit (RLIMIT_DATA, &r);
157#ifdef RLIMIT_RSS
158  // Resident set size.
159  getrlimit (RLIMIT_RSS, &r);
160  r.rlim_cur = limit;
161  setrlimit (RLIMIT_RSS, &r);
162#endif
163#endif
164}
165
166}
167
168static std::vector<const char *>
169toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
170  std::vector<const char *> Result;
171  for (StringRef S : Strings)
172    Result.push_back(Saver.save(S).data());
173  Result.push_back(nullptr);
174  return Result;
175}
176
177static bool Execute(ProcessInfo &PI, StringRef Program,
178                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
179                    ArrayRef<Optional<StringRef>> Redirects,
180                    unsigned MemoryLimit, std::string *ErrMsg) {
181  if (!llvm::sys::fs::exists(Program)) {
182    if (ErrMsg)
183      *ErrMsg = std::string("Executable \"") + Program.str() +
184                std::string("\" doesn't exist!");
185    return false;
186  }
187
188  BumpPtrAllocator Allocator;
189  StringSaver Saver(Allocator);
190  std::vector<const char *> ArgVector, EnvVector;
191  const char **Argv = nullptr;
192  const char **Envp = nullptr;
193  ArgVector = toNullTerminatedCStringArray(Args, Saver);
194  Argv = ArgVector.data();
195  if (Env) {
196    EnvVector = toNullTerminatedCStringArray(*Env, Saver);
197    Envp = EnvVector.data();
198  }
199
200  // If this OS has posix_spawn and there is no memory limit being implied, use
201  // posix_spawn.  It is more efficient than fork/exec.
202#ifdef HAVE_POSIX_SPAWN
203  if (MemoryLimit == 0) {
204    posix_spawn_file_actions_t FileActionsStore;
205    posix_spawn_file_actions_t *FileActions = nullptr;
206
207    // If we call posix_spawn_file_actions_addopen we have to make sure the
208    // c strings we pass to it stay alive until the call to posix_spawn,
209    // so we copy any StringRefs into this variable.
210    std::string RedirectsStorage[3];
211
212    if (!Redirects.empty()) {
213      assert(Redirects.size() == 3);
214      std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
215      for (int I = 0; I < 3; ++I) {
216        if (Redirects[I]) {
217          RedirectsStorage[I] = *Redirects[I];
218          RedirectsStr[I] = &RedirectsStorage[I];
219        }
220      }
221
222      FileActions = &FileActionsStore;
223      posix_spawn_file_actions_init(FileActions);
224
225      // Redirect stdin/stdout.
226      if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
227          RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
228        return false;
229      if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
230        // Just redirect stderr
231        if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
232          return false;
233      } else {
234        // If stdout and stderr should go to the same place, redirect stderr
235        // to the FD already open for stdout.
236        if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
237          return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
238      }
239    }
240
241    if (!Envp)
242#if !USE_NSGETENVIRON
243      Envp = const_cast<const char **>(environ);
244#else
245      // environ is missing in dylibs.
246      Envp = const_cast<const char **>(*_NSGetEnviron());
247#endif
248
249    // Explicitly initialized to prevent what appears to be a valgrind false
250    // positive.
251    pid_t PID = 0;
252    int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
253                          /*attrp*/ nullptr, const_cast<char **>(Argv),
254                          const_cast<char **>(Envp));
255
256    if (FileActions)
257      posix_spawn_file_actions_destroy(FileActions);
258
259    if (Err)
260     return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
261
262    PI.Pid = PID;
263    PI.Process = PID;
264
265    return true;
266  }
267#endif
268
269  // Create a child process.
270  int child = fork();
271  switch (child) {
272    // An error occurred:  Return to the caller.
273    case -1:
274      MakeErrMsg(ErrMsg, "Couldn't fork");
275      return false;
276
277    // Child process: Execute the program.
278    case 0: {
279      // Redirect file descriptors...
280      if (!Redirects.empty()) {
281        // Redirect stdin
282        if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
283        // Redirect stdout
284        if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
285        if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
286          // If stdout and stderr should go to the same place, redirect stderr
287          // to the FD already open for stdout.
288          if (-1 == dup2(1,2)) {
289            MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
290            return false;
291          }
292        } else {
293          // Just redirect stderr
294          if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
295        }
296      }
297
298      // Set memory limits
299      if (MemoryLimit!=0) {
300        SetMemoryLimits(MemoryLimit);
301      }
302
303      // Execute!
304      std::string PathStr = Program;
305      if (Envp != nullptr)
306        execve(PathStr.c_str(), const_cast<char **>(Argv),
307               const_cast<char **>(Envp));
308      else
309        execv(PathStr.c_str(), const_cast<char **>(Argv));
310      // If the execve() failed, we should exit. Follow Unix protocol and
311      // return 127 if the executable was not found, and 126 otherwise.
312      // Use _exit rather than exit so that atexit functions and static
313      // object destructors cloned from the parent process aren't
314      // redundantly run, and so that any data buffered in stdio buffers
315      // cloned from the parent aren't redundantly written out.
316      _exit(errno == ENOENT ? 127 : 126);
317    }
318
319    // Parent process: Break out of the switch to do our processing.
320    default:
321      break;
322  }
323
324  PI.Pid = child;
325  PI.Process = child;
326
327  return true;
328}
329
330namespace llvm {
331
332ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
333                      bool WaitUntilTerminates, std::string *ErrMsg) {
334  struct sigaction Act, Old;
335  assert(PI.Pid && "invalid pid to wait on, process not started?");
336
337  int WaitPidOptions = 0;
338  pid_t ChildPid = PI.Pid;
339  if (WaitUntilTerminates) {
340    SecondsToWait = 0;
341  } else if (SecondsToWait) {
342    // Install a timeout handler.  The handler itself does nothing, but the
343    // simple fact of having a handler at all causes the wait below to return
344    // with EINTR, unlike if we used SIG_IGN.
345    memset(&Act, 0, sizeof(Act));
346    Act.sa_handler = TimeOutHandler;
347    sigemptyset(&Act.sa_mask);
348    sigaction(SIGALRM, &Act, &Old);
349    alarm(SecondsToWait);
350  } else if (SecondsToWait == 0)
351    WaitPidOptions = WNOHANG;
352
353  // Parent process: Wait for the child process to terminate.
354  int status;
355  ProcessInfo WaitResult;
356
357  do {
358    WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
359  } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
360
361  if (WaitResult.Pid != PI.Pid) {
362    if (WaitResult.Pid == 0) {
363      // Non-blocking wait.
364      return WaitResult;
365    } else {
366      if (SecondsToWait && errno == EINTR) {
367        // Kill the child.
368        kill(PI.Pid, SIGKILL);
369
370        // Turn off the alarm and restore the signal handler
371        alarm(0);
372        sigaction(SIGALRM, &Old, nullptr);
373
374        // Wait for child to die
375        if (wait(&status) != ChildPid)
376          MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
377        else
378          MakeErrMsg(ErrMsg, "Child timed out", 0);
379
380        WaitResult.ReturnCode = -2; // Timeout detected
381        return WaitResult;
382      } else if (errno != EINTR) {
383        MakeErrMsg(ErrMsg, "Error waiting for child process");
384        WaitResult.ReturnCode = -1;
385        return WaitResult;
386      }
387    }
388  }
389
390  // We exited normally without timeout, so turn off the timer.
391  if (SecondsToWait && !WaitUntilTerminates) {
392    alarm(0);
393    sigaction(SIGALRM, &Old, nullptr);
394  }
395
396  // Return the proper exit status. Detect error conditions
397  // so we can return -1 for them and set ErrMsg informatively.
398  int result = 0;
399  if (WIFEXITED(status)) {
400    result = WEXITSTATUS(status);
401    WaitResult.ReturnCode = result;
402
403    if (result == 127) {
404      if (ErrMsg)
405        *ErrMsg = llvm::sys::StrError(ENOENT);
406      WaitResult.ReturnCode = -1;
407      return WaitResult;
408    }
409    if (result == 126) {
410      if (ErrMsg)
411        *ErrMsg = "Program could not be executed";
412      WaitResult.ReturnCode = -1;
413      return WaitResult;
414    }
415  } else if (WIFSIGNALED(status)) {
416    if (ErrMsg) {
417      *ErrMsg = strsignal(WTERMSIG(status));
418#ifdef WCOREDUMP
419      if (WCOREDUMP(status))
420        *ErrMsg += " (core dumped)";
421#endif
422    }
423    // Return a special value to indicate that the process received an unhandled
424    // signal during execution as opposed to failing to execute.
425    WaitResult.ReturnCode = -2;
426  }
427  return WaitResult;
428}
429
430std::error_code sys::ChangeStdinToBinary() {
431  // Do nothing, as Unix doesn't differentiate between text and binary.
432  return std::error_code();
433}
434
435std::error_code sys::ChangeStdoutToBinary() {
436  // Do nothing, as Unix doesn't differentiate between text and binary.
437  return std::error_code();
438}
439
440std::error_code
441llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
442                                 WindowsEncodingMethod Encoding /*unused*/) {
443  std::error_code EC;
444  llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
445
446  if (EC)
447    return EC;
448
449  OS << Contents;
450
451  if (OS.has_error())
452    return make_error_code(errc::io_error);
453
454  return EC;
455}
456
457bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
458                                                  ArrayRef<StringRef> Args) {
459  static long ArgMax = sysconf(_SC_ARG_MAX);
460  // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
461  // value for ARG_MAX on a POSIX compliant system.
462  static long ArgMin = _POSIX_ARG_MAX;
463
464  // This the same baseline used by xargs.
465  long EffectiveArgMax = 128 * 1024;
466
467  if (EffectiveArgMax > ArgMax)
468    EffectiveArgMax = ArgMax;
469  else if (EffectiveArgMax < ArgMin)
470    EffectiveArgMax = ArgMin;
471
472  // System says no practical limit.
473  if (ArgMax == -1)
474    return true;
475
476  // Conservatively account for space required by environment variables.
477  long HalfArgMax = EffectiveArgMax / 2;
478
479  size_t ArgLength = Program.size() + 1;
480  for (StringRef Arg : Args) {
481    // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
482    // does not have a constant unlike what the man pages would have you
483    // believe. Since this limit is pretty high, perform the check
484    // unconditionally rather than trying to be aggressive and limiting it to
485    // Linux only.
486    if (Arg.size() >= (32 * 4096))
487      return false;
488
489    ArgLength += Arg.size() + 1;
490    if (ArgLength > size_t(HalfArgMax)) {
491      return false;
492    }
493  }
494
495  return true;
496}
497}
498