Program.inc revision 234353
1213365Smarcel//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===//
2214006Smarcel//
3213365Smarcel//                     The LLVM Compiler Infrastructure
4213365Smarcel//
5213365Smarcel// This file is distributed under the University of Illinois Open Source
6213365Smarcel// License. See LICENSE.TXT for details.
7213365Smarcel//
8213365Smarcel//===----------------------------------------------------------------------===//
9213365Smarcel//
10213365Smarcel// This file implements the Unix specific portion of the Program class.
11213365Smarcel//
12213365Smarcel//===----------------------------------------------------------------------===//
13213365Smarcel
14213365Smarcel//===----------------------------------------------------------------------===//
15213365Smarcel//=== WARNING: Implementation here must contain only generic UNIX code that
16213365Smarcel//===          is guaranteed to work on *all* UNIX variants.
17213365Smarcel//===----------------------------------------------------------------------===//
18213365Smarcel
19213365Smarcel#include <llvm/Config/config.h>
20213365Smarcel#include "llvm/Support/FileSystem.h"
21213365Smarcel#include "Unix.h"
22213365Smarcel#if HAVE_SYS_STAT_H
23213365Smarcel#include <sys/stat.h>
24213365Smarcel#endif
25213365Smarcel#if HAVE_SYS_RESOURCE_H
26213365Smarcel#include <sys/resource.h>
27213365Smarcel#endif
28213365Smarcel#if HAVE_SIGNAL_H
29213365Smarcel#include <signal.h>
30213365Smarcel#endif
31213365Smarcel#if HAVE_FCNTL_H
32213365Smarcel#include <fcntl.h>
33213365Smarcel#endif
34213365Smarcel#ifdef HAVE_POSIX_SPAWN
35213365Smarcel#include <spawn.h>
36213365Smarcel#if !defined(__APPLE__)
37213365Smarcel  extern char **environ;
38214006Smarcel#else
39214006Smarcel#include <crt_externs.h> // _NSGetEnviron
40213365Smarcel#endif
41213365Smarcel#endif
42213365Smarcel
43213365Smarcelnamespace llvm {
44213365Smarcelusing namespace sys;
45228634Savg
46213365SmarcelProgram::Program() : Data_(0) {}
47213365Smarcel
48213365SmarcelProgram::~Program() {}
49213365Smarcel
50214006Smarcelunsigned Program::GetPid() const {
51213365Smarcel  uint64_t pid = reinterpret_cast<uint64_t>(Data_);
52213365Smarcel  return static_cast<unsigned>(pid);
53213365Smarcel}
54213365Smarcel
55213365Smarcel// This function just uses the PATH environment variable to find the program.
56213365SmarcelPath
57213365SmarcelProgram::FindProgramByName(const std::string& progName) {
58223919Sae
59214006Smarcel  // Check some degenerate cases
60213365Smarcel  if (progName.length() == 0) // no program
61213365Smarcel    return Path();
62213365Smarcel  Path temp;
63213365Smarcel  if (!temp.set(progName)) // invalid name
64213365Smarcel    return Path();
65213365Smarcel  // Use the given path verbatim if it contains any slashes; this matches
66213365Smarcel  // the behavior of sh(1) and friends.
67213365Smarcel  if (progName.find('/') != std::string::npos)
68213365Smarcel    return temp;
69213365Smarcel
70213365Smarcel  // At this point, the file name is valid and does not contain slashes. Search
71213365Smarcel  // for it through the directories specified in the PATH environment variable.
72213365Smarcel
73213365Smarcel  // Get the path. If its empty, we can't do anything to find it.
74213365Smarcel  const char *PathStr = getenv("PATH");
75213365Smarcel  if (PathStr == 0)
76213365Smarcel    return Path();
77213365Smarcel
78213365Smarcel  // Now we have a colon separated list of directories to search; try them.
79213365Smarcel  size_t PathLen = strlen(PathStr);
80213365Smarcel  while (PathLen) {
81213365Smarcel    // Find the first colon...
82213365Smarcel    const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
83213365Smarcel
84213365Smarcel    // Check to see if this first directory contains the executable...
85213365Smarcel    Path FilePath;
86213365Smarcel    if (FilePath.set(std::string(PathStr,Colon))) {
87213365Smarcel      FilePath.appendComponent(progName);
88213365Smarcel      if (FilePath.canExecute())
89214006Smarcel        return FilePath;                    // Found the executable!
90214006Smarcel    }
91214006Smarcel
92213365Smarcel    // Nope it wasn't in this directory, check the next path in the list!
93214006Smarcel    PathLen -= Colon-PathStr;
94214006Smarcel    PathStr = Colon;
95213365Smarcel
96214006Smarcel    // Advance past duplicate colons
97213365Smarcel    while (*PathStr == ':') {
98214006Smarcel      PathStr++;
99213365Smarcel      PathLen--;
100213365Smarcel    }
101213365Smarcel  }
102213365Smarcel  return Path();
103213365Smarcel}
104213365Smarcel
105213365Smarcelstatic bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) {
106213365Smarcel  if (Path == 0) // Noop
107213365Smarcel    return false;
108214006Smarcel  const char *File;
109214006Smarcel  if (Path->isEmpty())
110214006Smarcel    // Redirect empty paths to /dev/null
111214006Smarcel    File = "/dev/null";
112214006Smarcel  else
113214006Smarcel    File = Path->c_str();
114214006Smarcel
115214006Smarcel  // Open the file
116214006Smarcel  int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
117214006Smarcel  if (InFD == -1) {
118213365Smarcel    MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for "
119213365Smarcel              + (FD == 0 ? "input" : "output"));
120214006Smarcel    return true;
121214006Smarcel  }
122253910Smarcel
123214006Smarcel  // Install it as the requested FD
124213365Smarcel  if (dup2(InFD, FD) == -1) {
125213365Smarcel    MakeErrMsg(ErrMsg, "Cannot dup2");
126213365Smarcel    close(InFD);
127213365Smarcel    return true;
128213365Smarcel  }
129213365Smarcel  close(InFD);      // Close the original FD
130213365Smarcel  return false;
131213365Smarcel}
132213365Smarcel
133213365Smarcel#ifdef HAVE_POSIX_SPAWN
134213365Smarcelstatic bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg,
135213365Smarcel                          posix_spawn_file_actions_t *FileActions) {
136213365Smarcel  if (Path == 0) // Noop
137213365Smarcel    return false;
138213365Smarcel  const char *File;
139213365Smarcel  if (Path->isEmpty())
140213365Smarcel    // Redirect empty paths to /dev/null
141213365Smarcel    File = "/dev/null";
142213365Smarcel  else
143213365Smarcel    File = Path->c_str();
144213365Smarcel
145213365Smarcel  if (int Err = posix_spawn_file_actions_addopen(FileActions, FD,
146213365Smarcel                            File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666))
147213365Smarcel    return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
148213365Smarcel  return false;
149213365Smarcel}
150213365Smarcel#endif
151213365Smarcel
152213365Smarcelstatic void TimeOutHandler(int Sig) {
153213365Smarcel}
154213365Smarcel
155213365Smarcelstatic void SetMemoryLimits (unsigned size)
156213365Smarcel{
157213365Smarcel#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
158213365Smarcel  struct rlimit r;
159213365Smarcel  __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
160213365Smarcel
161213365Smarcel  // Heap size
162213365Smarcel  getrlimit (RLIMIT_DATA, &r);
163213365Smarcel  r.rlim_cur = limit;
164213365Smarcel  setrlimit (RLIMIT_DATA, &r);
165213365Smarcel#ifdef RLIMIT_RSS
166213365Smarcel  // Resident set size.
167213365Smarcel  getrlimit (RLIMIT_RSS, &r);
168213365Smarcel  r.rlim_cur = limit;
169213365Smarcel  setrlimit (RLIMIT_RSS, &r);
170213365Smarcel#endif
171213365Smarcel#ifdef RLIMIT_AS  // e.g. NetBSD doesn't have it.
172213365Smarcel  // Virtual memory.
173213365Smarcel  getrlimit (RLIMIT_AS, &r);
174213365Smarcel  r.rlim_cur = limit;
175213365Smarcel  setrlimit (RLIMIT_AS, &r);
176213365Smarcel#endif
177213365Smarcel#endif
178213365Smarcel}
179213365Smarcel
180213365Smarcelbool
181213365SmarcelProgram::Execute(const Path &path, const char **args, const char **envp,
182213365Smarcel                 const Path **redirects, unsigned memoryLimit,
183213365Smarcel                  std::string *ErrMsg) {
184213365Smarcel  // If this OS has posix_spawn and there is no memory limit being implied, use
185213365Smarcel  // posix_spawn.  It is more efficient than fork/exec.
186213365Smarcel#ifdef HAVE_POSIX_SPAWN
187213365Smarcel  if (memoryLimit == 0) {
188213365Smarcel    posix_spawn_file_actions_t FileActionsStore;
189213365Smarcel    posix_spawn_file_actions_t *FileActions = 0;
190213365Smarcel
191213365Smarcel    if (redirects) {
192213365Smarcel      FileActions = &FileActionsStore;
193213365Smarcel      posix_spawn_file_actions_init(FileActions);
194213365Smarcel
195213365Smarcel      // Redirect stdin/stdout.
196213365Smarcel      if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) ||
197213365Smarcel          RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions))
198213365Smarcel        return false;
199213365Smarcel      if (redirects[1] == 0 || redirects[2] == 0 ||
200213365Smarcel          *redirects[1] != *redirects[2]) {
201213365Smarcel        // Just redirect stderr
202213365Smarcel        if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false;
203213365Smarcel      } else {
204213365Smarcel        // If stdout and stderr should go to the same place, redirect stderr
205214006Smarcel        // to the FD already open for stdout.
206214006Smarcel        if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
207213365Smarcel          return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
208213365Smarcel      }
209213365Smarcel    }
210214006Smarcel
211213365Smarcel    if (!envp)
212213365Smarcel#if !defined(__APPLE__)
213214006Smarcel      envp = const_cast<const char **>(environ);
214214006Smarcel#else
215213365Smarcel      // environ is missing in dylibs.
216213365Smarcel      envp = const_cast<const char **>(*_NSGetEnviron());
217213365Smarcel#endif
218214006Smarcel
219213365Smarcel    // Explicitly initialized to prevent what appears to be a valgrind false
220213365Smarcel    // positive.
221213365Smarcel    pid_t PID = 0;
222213365Smarcel    int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0,
223213365Smarcel                          const_cast<char **>(args), const_cast<char **>(envp));
224213365Smarcel
225214006Smarcel    if (FileActions)
226213365Smarcel      posix_spawn_file_actions_destroy(FileActions);
227213365Smarcel
228213365Smarcel    if (Err)
229213365Smarcel     return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
230213365Smarcel
231213365Smarcel    Data_ = reinterpret_cast<void*>(PID);
232213365Smarcel    return true;
233213365Smarcel  }
234213365Smarcel#endif
235214006Smarcel
236213365Smarcel  // Create a child process.
237213365Smarcel  int child = fork();
238213365Smarcel  switch (child) {
239213365Smarcel    // An error occurred:  Return to the caller.
240213365Smarcel    case -1:
241214006Smarcel      MakeErrMsg(ErrMsg, "Couldn't fork");
242214006Smarcel      return false;
243213365Smarcel
244213365Smarcel    // Child process: Execute the program.
245214006Smarcel    case 0: {
246214006Smarcel      // Redirect file descriptors...
247213365Smarcel      if (redirects) {
248213365Smarcel        // Redirect stdin
249214006Smarcel        if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; }
250214006Smarcel        // Redirect stdout
251214006Smarcel        if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; }
252213365Smarcel        if (redirects[1] && redirects[2] &&
253213365Smarcel            *(redirects[1]) == *(redirects[2])) {
254214006Smarcel          // If stdout and stderr should go to the same place, redirect stderr
255214006Smarcel          // to the FD already open for stdout.
256214006Smarcel          if (-1 == dup2(1,2)) {
257213365Smarcel            MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
258214006Smarcel            return false;
259214006Smarcel          }
260214006Smarcel        } else {
261214006Smarcel          // Just redirect stderr
262214006Smarcel          if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; }
263214006Smarcel        }
264214006Smarcel      }
265213365Smarcel
266213365Smarcel      // Set memory limits
267214006Smarcel      if (memoryLimit!=0) {
268214006Smarcel        SetMemoryLimits(memoryLimit);
269214006Smarcel      }
270213365Smarcel
271214006Smarcel      // Execute!
272214006Smarcel      if (envp != 0)
273214006Smarcel        execve(path.c_str(),
274214006Smarcel               const_cast<char **>(args),
275214006Smarcel               const_cast<char **>(envp));
276214006Smarcel      else
277214006Smarcel        execv(path.c_str(),
278214006Smarcel              const_cast<char **>(args));
279214006Smarcel      // If the execve() failed, we should exit. Follow Unix protocol and
280214006Smarcel      // return 127 if the executable was not found, and 126 otherwise.
281214006Smarcel      // Use _exit rather than exit so that atexit functions and static
282214006Smarcel      // object destructors cloned from the parent process aren't
283213365Smarcel      // redundantly run, and so that any data buffered in stdio buffers
284213365Smarcel      // cloned from the parent aren't redundantly written out.
285213365Smarcel      _exit(errno == ENOENT ? 127 : 126);
286214006Smarcel    }
287214006Smarcel
288214006Smarcel    // Parent process: Break out of the switch to do our processing.
289214006Smarcel    default:
290214006Smarcel      break;
291214006Smarcel  }
292214006Smarcel
293214006Smarcel  Data_ = reinterpret_cast<void*>(child);
294214006Smarcel
295214006Smarcel  return true;
296214006Smarcel}
297214006Smarcel
298214006Smarcelint
299214006SmarcelProgram::Wait(const sys::Path &path,
300214006Smarcel              unsigned secondsToWait,
301214006Smarcel              std::string* ErrMsg)
302214006Smarcel{
303214006Smarcel#ifdef HAVE_SYS_WAIT_H
304214006Smarcel  struct sigaction Act, Old;
305214006Smarcel
306214006Smarcel  if (Data_ == 0) {
307214006Smarcel    MakeErrMsg(ErrMsg, "Process not started!");
308214006Smarcel    return -1;
309214006Smarcel  }
310214006Smarcel
311214006Smarcel  // Install a timeout handler.  The handler itself does nothing, but the simple
312214006Smarcel  // fact of having a handler at all causes the wait below to return with EINTR,
313214006Smarcel  // unlike if we used SIG_IGN.
314214006Smarcel  if (secondsToWait) {
315214006Smarcel    memset(&Act, 0, sizeof(Act));
316214006Smarcel    Act.sa_handler = TimeOutHandler;
317214006Smarcel    sigemptyset(&Act.sa_mask);
318214006Smarcel    sigaction(SIGALRM, &Act, &Old);
319214006Smarcel    alarm(secondsToWait);
320214006Smarcel  }
321214006Smarcel
322213365Smarcel  // Parent process: Wait for the child process to terminate.
323213365Smarcel  int status;
324214006Smarcel  uint64_t pid = reinterpret_cast<uint64_t>(Data_);
325214006Smarcel  pid_t child = static_cast<pid_t>(pid);
326214006Smarcel  while (waitpid(pid, &status, 0) != child)
327214006Smarcel    if (secondsToWait && errno == EINTR) {
328214006Smarcel      // Kill the child.
329214006Smarcel      kill(child, SIGKILL);
330214006Smarcel
331214006Smarcel      // Turn off the alarm and restore the signal handler
332214006Smarcel      alarm(0);
333214006Smarcel      sigaction(SIGALRM, &Old, 0);
334214006Smarcel
335214006Smarcel      // Wait for child to die
336214006Smarcel      if (wait(&status) != child)
337214006Smarcel        MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
338214006Smarcel      else
339214006Smarcel        MakeErrMsg(ErrMsg, "Child timed out", 0);
340214006Smarcel
341213365Smarcel      return -2;   // Timeout detected
342214006Smarcel    } else if (errno != EINTR) {
343214006Smarcel      MakeErrMsg(ErrMsg, "Error waiting for child process");
344214006Smarcel      return -1;
345213365Smarcel    }
346214006Smarcel
347214006Smarcel  // We exited normally without timeout, so turn off the timer.
348214006Smarcel  if (secondsToWait) {
349214006Smarcel    alarm(0);
350214006Smarcel    sigaction(SIGALRM, &Old, 0);
351214006Smarcel  }
352214006Smarcel
353214006Smarcel  // Return the proper exit status. Detect error conditions
354213365Smarcel  // so we can return -1 for them and set ErrMsg informatively.
355214006Smarcel  int result = 0;
356214006Smarcel  if (WIFEXITED(status)) {
357214006Smarcel    result = WEXITSTATUS(status);
358214006Smarcel#ifdef HAVE_POSIX_SPAWN
359214006Smarcel    // The posix_spawn child process returns 127 on any kind of error.
360214006Smarcel    // Following the POSIX convention for command-line tools (which posix_spawn
361214006Smarcel    // itself apparently does not), check to see if the failure was due to some
362214006Smarcel    // reason other than the file not existing, and return 126 in this case.
363214006Smarcel    bool Exists;
364214006Smarcel    if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists)
365214006Smarcel      result = 126;
366214006Smarcel#endif
367214006Smarcel    if (result == 127) {
368214006Smarcel      if (ErrMsg)
369214006Smarcel        *ErrMsg = llvm::sys::StrError(ENOENT);
370214006Smarcel      return -1;
371214006Smarcel    }
372214006Smarcel    if (result == 126) {
373214006Smarcel      if (ErrMsg)
374214006Smarcel        *ErrMsg = "Program could not be executed";
375214006Smarcel      return -1;
376214006Smarcel    }
377214006Smarcel  } else if (WIFSIGNALED(status)) {
378214006Smarcel    if (ErrMsg) {
379214006Smarcel      *ErrMsg = strsignal(WTERMSIG(status));
380214006Smarcel#ifdef WCOREDUMP
381214006Smarcel      if (WCOREDUMP(status))
382214006Smarcel        *ErrMsg += " (core dumped)";
383214006Smarcel#endif
384214006Smarcel    }
385214006Smarcel    // Return a special value to indicate that the process received an unhandled
386214006Smarcel    // signal during execution as opposed to failing to execute.
387214006Smarcel    return -2;
388214006Smarcel  }
389214006Smarcel  return result;
390214006Smarcel#else
391214006Smarcel  if (ErrMsg)
392214006Smarcel    *ErrMsg = "Program::Wait is not implemented on this platform yet!";
393214006Smarcel  return -1;
394214006Smarcel#endif
395214006Smarcel}
396214006Smarcel
397214006Smarcelbool
398214006SmarcelProgram::Kill(std::string* ErrMsg) {
399214006Smarcel  if (Data_ == 0) {
400214006Smarcel    MakeErrMsg(ErrMsg, "Process not started!");
401214006Smarcel    return true;
402214006Smarcel  }
403214006Smarcel
404214006Smarcel  uint64_t pid64 = reinterpret_cast<uint64_t>(Data_);
405214006Smarcel  pid_t pid = static_cast<pid_t>(pid64);
406214006Smarcel
407214006Smarcel  if (kill(pid, SIGKILL) != 0) {
408214006Smarcel    MakeErrMsg(ErrMsg, "The process couldn't be killed!");
409214006Smarcel    return true;
410214006Smarcel  }
411214006Smarcel
412214006Smarcel  return false;
413214006Smarcel}
414214006Smarcel
415214006Smarcelerror_code Program::ChangeStdinToBinary(){
416214006Smarcel  // Do nothing, as Unix doesn't differentiate between text and binary.
417214006Smarcel  return make_error_code(errc::success);
418214006Smarcel}
419214006Smarcel
420214006Smarcelerror_code Program::ChangeStdoutToBinary(){
421214006Smarcel  // Do nothing, as Unix doesn't differentiate between text and binary.
422214006Smarcel  return make_error_code(errc::success);
423214006Smarcel}
424213365Smarcel
425214006Smarcelerror_code Program::ChangeStderrToBinary(){
426214006Smarcel  // Do nothing, as Unix doesn't differentiate between text and binary.
427213365Smarcel  return make_error_code(errc::success);
428214006Smarcel}
429214006Smarcel
430214006Smarcel}
431214006Smarcel