LLVM  3.7.0
Unix/Process.inc
Go to the documentation of this file.
1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- 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 provides the generic Unix implementation of the Process class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Unix.h"
15 #include "llvm/ADT/Hashing.h"
16 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Mutex.h"
20 #include "llvm/Support/TimeValue.h"
21 #if HAVE_FCNTL_H
22 #include <fcntl.h>
23 #endif
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27 #ifdef HAVE_SYS_RESOURCE_H
28 #include <sys/resource.h>
29 #endif
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #if HAVE_SIGNAL_H
34 #include <signal.h>
35 #endif
36 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
37 // <stdlib.h> instead. Unix.h includes this for us already.
38 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
39  !defined(__OpenBSD__) && !defined(__Bitrig__)
40 #include <malloc.h>
41 #endif
42 #if defined(HAVE_MALLCTL)
43 #include <malloc_np.h>
44 #endif
45 #ifdef HAVE_MALLOC_MALLOC_H
46 #include <malloc/malloc.h>
47 #endif
48 #ifdef HAVE_SYS_IOCTL_H
49 # include <sys/ioctl.h>
50 #endif
51 #ifdef HAVE_TERMIOS_H
52 # include <termios.h>
53 #endif
54 
55 //===----------------------------------------------------------------------===//
56 //=== WARNING: Implementation here must contain only generic UNIX code that
57 //=== is guaranteed to work on *all* UNIX variants.
58 //===----------------------------------------------------------------------===//
59 
60 using namespace llvm;
61 using namespace sys;
62 
63 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
64 #if defined(HAVE_GETRUSAGE)
65  struct rusage RU;
66  ::getrusage(RUSAGE_SELF, &RU);
67  return std::make_pair(
68  TimeValue(
69  static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
70  static_cast<TimeValue::NanoSecondsType>(
71  RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
72  TimeValue(
73  static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
74  static_cast<TimeValue::NanoSecondsType>(
75  RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
76 #else
77 #warning Cannot get usage times on this platform
78  return std::make_pair(TimeValue(), TimeValue());
79 #endif
80 }
81 
82 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
83 // offset in mmap(3) should be aligned to the AllocationGranularity.
84 unsigned Process::getPageSize() {
85 #if defined(HAVE_GETPAGESIZE)
86  static const int page_size = ::getpagesize();
87 #elif defined(HAVE_SYSCONF)
88  static long page_size = ::sysconf(_SC_PAGE_SIZE);
89 #else
90 #warning Cannot get the page size on this machine
91 #endif
92  return static_cast<unsigned>(page_size);
93 }
94 
95 size_t Process::GetMallocUsage() {
96 #if defined(HAVE_MALLINFO)
97  struct mallinfo mi;
98  mi = ::mallinfo();
99  return mi.uordblks;
100 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
101  malloc_statistics_t Stats;
102  malloc_zone_statistics(malloc_default_zone(), &Stats);
103  return Stats.size_in_use; // darwin
104 #elif defined(HAVE_MALLCTL)
105  size_t alloc, sz;
106  sz = sizeof(size_t);
107  if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
108  return alloc;
109  return 0;
110 #elif defined(HAVE_SBRK)
111  // Note this is only an approximation and more closely resembles
112  // the value returned by mallinfo in the arena field.
113  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
114  char *EndOfMemory = (char*)sbrk(0);
115  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
116  return EndOfMemory - StartOfMemory;
117  return 0;
118 #else
119 #warning Cannot get malloc info on this platform
120  return 0;
121 #endif
122 }
123 
124 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
125  TimeValue &sys_time) {
126  elapsed = TimeValue::now();
127  std::tie(user_time, sys_time) = getRUsageTimes();
128 }
129 
130 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
131 #include <mach/mach.h>
132 #endif
133 
134 // Some LLVM programs such as bugpoint produce core files as a normal part of
135 // their operation. To prevent the disk from filling up, this function
136 // does what's necessary to prevent their generation.
138 #if HAVE_SETRLIMIT
139  struct rlimit rlim;
140  rlim.rlim_cur = rlim.rlim_max = 0;
141  setrlimit(RLIMIT_CORE, &rlim);
142 #endif
143 
144 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
145  // Disable crash reporting on Mac OS X 10.0-10.4
146 
147  // get information about the original set of exception ports for the task
148  mach_msg_type_number_t Count = 0;
149  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
150  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
151  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
152  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
153  kern_return_t err =
154  task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
155  &Count, OriginalPorts, OriginalBehaviors,
156  OriginalFlavors);
157  if (err == KERN_SUCCESS) {
158  // replace each with MACH_PORT_NULL.
159  for (unsigned i = 0; i != Count; ++i)
160  task_set_exception_ports(mach_task_self(), OriginalMasks[i],
161  MACH_PORT_NULL, OriginalBehaviors[i],
162  OriginalFlavors[i]);
163  }
164 
165  // Disable crash reporting on Mac OS X 10.5
166  signal(SIGABRT, _exit);
167  signal(SIGILL, _exit);
168  signal(SIGFPE, _exit);
169  signal(SIGSEGV, _exit);
170  signal(SIGBUS, _exit);
171 #endif
172 }
173 
175  std::string NameStr = Name.str();
176  const char *Val = ::getenv(NameStr.c_str());
177  if (!Val)
178  return None;
179  return std::string(Val);
180 }
181 
182 std::error_code
184  ArrayRef<const char *> ArgsIn,
186  ArgsOut.append(ArgsIn.begin(), ArgsIn.end());
187 
188  return std::error_code();
189 }
190 
191 namespace {
192 class FDCloser {
193 public:
194  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
195  void keepOpen() { KeepOpen = true; }
196  ~FDCloser() {
197  if (!KeepOpen && FD >= 0)
198  ::close(FD);
199  }
200 
201 private:
202  FDCloser(const FDCloser &) = delete;
203  void operator=(const FDCloser &) = delete;
204 
205  int &FD;
206  bool KeepOpen;
207 };
208 }
209 
210 std::error_code Process::FixupStandardFileDescriptors() {
211  int NullFD = -1;
212  FDCloser FDC(NullFD);
213  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
214  for (int StandardFD : StandardFDs) {
215  struct stat st;
216  errno = 0;
217  while (fstat(StandardFD, &st) < 0) {
218  assert(errno && "expected errno to be set if fstat failed!");
219  // fstat should return EBADF if the file descriptor is closed.
220  if (errno == EBADF)
221  break;
222  // retry fstat if we got EINTR, otherwise bubble up the failure.
223  if (errno != EINTR)
224  return std::error_code(errno, std::generic_category());
225  }
226  // if fstat succeeds, move on to the next FD.
227  if (!errno)
228  continue;
229  assert(errno == EBADF && "expected errno to have EBADF at this point!");
230 
231  if (NullFD < 0) {
232  while ((NullFD = open("/dev/null", O_RDWR)) < 0) {
233  if (errno == EINTR)
234  continue;
235  return std::error_code(errno, std::generic_category());
236  }
237  }
238 
239  if (NullFD == StandardFD)
240  FDC.keepOpen();
241  else if (dup2(NullFD, StandardFD) < 0)
242  return std::error_code(errno, std::generic_category());
243  }
244  return std::error_code();
245 }
246 
247 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
248  // Create a signal set filled with *all* signals.
249  sigset_t FullSet;
250  if (sigfillset(&FullSet) < 0)
251  return std::error_code(errno, std::generic_category());
252  // Atomically swap our current signal mask with a full mask.
253  sigset_t SavedSet;
254 #if LLVM_ENABLE_THREADS
255  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
256  return std::error_code(EC, std::generic_category());
257 #else
258  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
259  return std::error_code(errno, std::generic_category());
260 #endif
261  // Attempt to close the file descriptor.
262  // We need to save the error, if one occurs, because our subsequent call to
263  // pthread_sigmask might tamper with errno.
264  int ErrnoFromClose = 0;
265  if (::close(FD) < 0)
266  ErrnoFromClose = errno;
267  // Restore the signal mask back to what we saved earlier.
268  int EC = 0;
269 #if LLVM_ENABLE_THREADS
270  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
271 #else
272  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
273  EC = errno;
274 #endif
275  // The error code from close takes precedence over the one from
276  // pthread_sigmask.
277  if (ErrnoFromClose)
278  return std::error_code(ErrnoFromClose, std::generic_category());
279  return std::error_code(EC, std::generic_category());
280 }
281 
283  return FileDescriptorIsDisplayed(STDIN_FILENO);
284 }
285 
287  return FileDescriptorIsDisplayed(STDOUT_FILENO);
288 }
289 
291  return FileDescriptorIsDisplayed(STDERR_FILENO);
292 }
293 
295 #if HAVE_ISATTY
296  return isatty(fd);
297 #else
298  // If we don't have isatty, just return false.
299  return false;
300 #endif
301 }
302 
303 static unsigned getColumns(int FileID) {
304  // If COLUMNS is defined in the environment, wrap to that many columns.
305  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
306  int Columns = std::atoi(ColumnsStr);
307  if (Columns > 0)
308  return Columns;
309  }
310 
311  unsigned Columns = 0;
312 
313 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
314  // Try to determine the width of the terminal.
315  struct winsize ws;
316  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
317  Columns = ws.ws_col;
318 #endif
319 
320  return Columns;
321 }
322 
323 unsigned Process::StandardOutColumns() {
324  if (!StandardOutIsDisplayed())
325  return 0;
326 
327  return getColumns(1);
328 }
329 
330 unsigned Process::StandardErrColumns() {
331  if (!StandardErrIsDisplayed())
332  return 0;
333 
334  return getColumns(2);
335 }
336 
337 #ifdef HAVE_TERMINFO
338 // We manually declare these extern functions because finding the correct
339 // headers from various terminfo, curses, or other sources is harder than
340 // writing their specs down.
341 extern "C" int setupterm(char *term, int filedes, int *errret);
342 extern "C" struct term *set_curterm(struct term *termp);
343 extern "C" int del_curterm(struct term *termp);
344 extern "C" int tigetnum(char *capname);
345 #endif
346 
347 #ifdef HAVE_TERMINFO
348 static ManagedStatic<sys::Mutex> TermColorMutex;
349 #endif
350 
351 static bool terminalHasColors(int fd) {
352 #ifdef HAVE_TERMINFO
353  // First, acquire a global lock because these C routines are thread hostile.
354  MutexGuard G(*TermColorMutex);
355 
356  int errret = 0;
357  if (setupterm((char *)nullptr, fd, &errret) != 0)
358  // Regardless of why, if we can't get terminfo, we shouldn't try to print
359  // colors.
360  return false;
361 
362  // Test whether the terminal as set up supports color output. How to do this
363  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
364  // would be nice to avoid a dependency on curses proper when we can make do
365  // with a minimal terminfo parsing library. Also, we don't really care whether
366  // the terminal supports the curses-specific color changing routines, merely
367  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
368  // strategy here is just to query the baseline colors capability and if it
369  // supports colors at all to assume it will translate the escape codes into
370  // whatever range of colors it does support. We can add more detailed tests
371  // here if users report them as necessary.
372  //
373  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
374  // the terminfo says that no colors are supported.
375  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
376 
377  // Now extract the structure allocated by setupterm and free its memory
378  // through a really silly dance.
379  struct term *termp = set_curterm((struct term *)nullptr);
380  (void)del_curterm(termp); // Drop any errors here.
381 
382  // Return true if we found a color capabilities for the current terminal.
383  if (HasColors)
384  return true;
385 #endif
386 
387  // Otherwise, be conservative.
388  return false;
389 }
390 
392  // A file descriptor has colors if it is displayed and the terminal has
393  // colors.
394  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
395 }
396 
398  return FileDescriptorHasColors(STDOUT_FILENO);
399 }
400 
402  return FileDescriptorHasColors(STDERR_FILENO);
403 }
404 
405 void Process::UseANSIEscapeCodes(bool /*enable*/) {
406  // No effect.
407 }
408 
410  // No, we use ANSI escape sequences.
411  return false;
412 }
413 
414 const char *Process::OutputColor(char code, bool bold, bool bg) {
415  return colorcodes[bg?1:0][bold?1:0][code&7];
416 }
417 
418 const char *Process::OutputBold(bool bg) {
419  return "\033[1m";
420 }
421 
422 const char *Process::OutputReverse() {
423  return "\033[7m";
424 }
425 
426 const char *Process::ResetColor() {
427  return "\033[0m";
428 }
429 
430 #if !defined(HAVE_DECL_ARC4RANDOM) || !HAVE_DECL_ARC4RANDOM
431 static unsigned GetRandomNumberSeed() {
432  // Attempt to get the initial seed from /dev/urandom, if possible.
433  if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
434  unsigned seed;
435  int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
436  ::fclose(RandomSource);
437 
438  // Return the seed if the read was successful.
439  if (count == 1)
440  return seed;
441  }
442 
443  // Otherwise, swizzle the current time and the process ID to form a reasonable
444  // seed.
445  TimeValue Now = TimeValue::now();
446  return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
447 }
448 #endif
449 
451 #if defined(HAVE_DECL_ARC4RANDOM) && HAVE_DECL_ARC4RANDOM
452  return arc4random();
453 #else
454  static int x = (::srand(GetRandomNumberSeed()), 0);
455  (void)x;
456  return ::rand();
457 #endif
458 }
const NoneType None
Definition: None.h:23
static TimeValue now()
This is a static constructor that returns a TimeValue that represents the current time...
static const char * ResetColor()
Resets the terminals colors, or returns an escape sequence to do so.
static const char * OutputColor(char c, bool bold, bool bg)
This function returns the colorcode escape sequences.
iterator end() const
Definition: ArrayRef.h:123
static bool StandardErrHasColors()
This function determines whether the terminal connected to standard error supports colors...
static bool FileDescriptorHasColors(int fd)
This function determines if the given file descriptor is displayd and supports colors.
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:188
static bool FileDescriptorIsDisplayed(int fd)
This function determines if the given file descriptor is connected to a "tty" or "console" window...
static std::error_code FixupStandardFileDescriptors()
static bool ColorNeedsFlush()
Whether changing colors requires the output to be flushed.
static const char * OutputReverse()
This function returns the escape sequence to reverse forground and background colors.
static const char colorcodes[2][2][8][10]
Definition: Process.cpp:71
block placement Basic Block Placement Stats
#define false
Definition: ConvertUTF.c:65
#define G(x, y, z)
Definition: MD5.cpp:52
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
static bool StandardInIsUserInput()
This function determines if the standard input is connected directly to a user's input (keyboard prob...
static bool StandardOutIsDisplayed()
This function determines if the standard output is connected to a "tty" or "console" window...
static void UseANSIEscapeCodes(bool enable)
Enables or disables whether ANSI escape sequences are used to output colors.
Instances of this class acquire a given Mutex Lock when constructed and hold that lock until destruct...
Definition: MutexGuard.h:27
static unsigned StandardOutColumns()
This function determines the number of columns in the window if standard output is connected to a "tt...
static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, TimeValue &sys_time)
This static function will set user_time to the amount of CPU time spent in user (non-kernel) mode and...
static std::error_code GetArgumentVector(SmallVectorImpl< const char * > &Args, ArrayRef< const char * > ArgsFromMain, SpecificBumpPtrAllocator< char > &ArgAllocator)
This function returns a SmallVector containing the arguments passed from the operating system to the ...
iterator begin() const
Definition: ArrayRef.h:122
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:416
static size_t GetMallocUsage()
Return process memory usage.
static unsigned getPageSize()
static bool StandardErrIsDisplayed()
This function determines if the standard error is connected to a "tty" or "console" window...
static void PreventCoreFiles()
This function makes the necessary calls to the operating system to prevent core files or any other ki...
static unsigned StandardErrColumns()
This function determines the number of columns in the window if standard error is connected to a "tty...
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
Definition: Allocator.h:349
static bool StandardOutHasColors()
This function determines whether the terminal connected to standard output supports colors...
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:603
static unsigned GetRandomNumber()
Get the result of a process wide random number generator.
static const char * OutputBold(bool bg)
Same as OutputColor, but only enables the bold attribute.
static std::error_code SafelyCloseFileDescriptor(int FD)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:61
static Optional< std::string > GetEnv(StringRef name)