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