LLVM  7.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"
17 #include "llvm/Config/config.h"
19 #include "llvm/Support/Mutex.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, and OpenBSD 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__)
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<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
64 #if defined(HAVE_GETRUSAGE)
65  struct rusage RU;
66  ::getrusage(RUSAGE_SELF, &RU);
67  return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
68 #else
69 #warning Cannot get usage times on this platform
70  return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() };
71 #endif
72 }
73 
74 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
75 // offset in mmap(3) should be aligned to the AllocationGranularity.
76 unsigned Process::getPageSize() {
77 #if defined(HAVE_GETPAGESIZE)
78  static const int page_size = ::getpagesize();
79 #elif defined(HAVE_SYSCONF)
80  static long page_size = ::sysconf(_SC_PAGE_SIZE);
81 #else
82 #error Cannot get the page size on this machine
83 #endif
84  return static_cast<unsigned>(page_size);
85 }
86 
87 size_t Process::GetMallocUsage() {
88 #if defined(HAVE_MALLINFO)
89  struct mallinfo mi;
90  mi = ::mallinfo();
91  return mi.uordblks;
92 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
93  malloc_statistics_t Stats;
94  malloc_zone_statistics(malloc_default_zone(), &Stats);
95  return Stats.size_in_use; // darwin
96 #elif defined(HAVE_MALLCTL)
97  size_t alloc, sz;
98  sz = sizeof(size_t);
99  if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
100  return alloc;
101  return 0;
102 #elif defined(HAVE_SBRK)
103  // Note this is only an approximation and more closely resembles
104  // the value returned by mallinfo in the arena field.
105  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
106  char *EndOfMemory = (char*)sbrk(0);
107  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
108  return EndOfMemory - StartOfMemory;
109  return 0;
110 #else
111 #warning Cannot get malloc info on this platform
112  return 0;
113 #endif
114 }
115 
116 void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
117  std::chrono::nanoseconds &sys_time) {
118  elapsed = std::chrono::system_clock::now();
119  std::tie(user_time, sys_time) = getRUsageTimes();
120 }
121 
122 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
123 #include <mach/mach.h>
124 #endif
125 
126 // Some LLVM programs such as bugpoint produce core files as a normal part of
127 // their operation. To prevent the disk from filling up, this function
128 // does what's necessary to prevent their generation.
130 #if HAVE_SETRLIMIT
131  struct rlimit rlim;
132  rlim.rlim_cur = rlim.rlim_max = 0;
133  setrlimit(RLIMIT_CORE, &rlim);
134 #endif
135 
136 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
137  // Disable crash reporting on Mac OS X 10.0-10.4
138 
139  // get information about the original set of exception ports for the task
140  mach_msg_type_number_t Count = 0;
141  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
142  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
143  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
144  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
145  kern_return_t err =
146  task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
147  &Count, OriginalPorts, OriginalBehaviors,
148  OriginalFlavors);
149  if (err == KERN_SUCCESS) {
150  // replace each with MACH_PORT_NULL.
151  for (unsigned i = 0; i != Count; ++i)
152  task_set_exception_ports(mach_task_self(), OriginalMasks[i],
153  MACH_PORT_NULL, OriginalBehaviors[i],
154  OriginalFlavors[i]);
155  }
156 
157  // Disable crash reporting on Mac OS X 10.5
158  signal(SIGABRT, _exit);
159  signal(SIGILL, _exit);
160  signal(SIGFPE, _exit);
161  signal(SIGSEGV, _exit);
162  signal(SIGBUS, _exit);
163 #endif
164 
165  coreFilesPrevented = true;
166 }
167 
169  std::string NameStr = Name.str();
170  const char *Val = ::getenv(NameStr.c_str());
171  if (!Val)
172  return None;
173  return std::string(Val);
174 }
175 
176 namespace {
177 class FDCloser {
178 public:
179  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
180  void keepOpen() { KeepOpen = true; }
181  ~FDCloser() {
182  if (!KeepOpen && FD >= 0)
183  ::close(FD);
184  }
185 
186 private:
187  FDCloser(const FDCloser &) = delete;
188  void operator=(const FDCloser &) = delete;
189 
190  int &FD;
191  bool KeepOpen;
192 };
193 }
194 
195 std::error_code Process::FixupStandardFileDescriptors() {
196  int NullFD = -1;
197  FDCloser FDC(NullFD);
198  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
199  for (int StandardFD : StandardFDs) {
200  struct stat st;
201  errno = 0;
202  if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
203  assert(errno && "expected errno to be set if fstat failed!");
204  // fstat should return EBADF if the file descriptor is closed.
205  if (errno != EBADF)
206  return std::error_code(errno, std::generic_category());
207  }
208  // if fstat succeeds, move on to the next FD.
209  if (!errno)
210  continue;
211  assert(errno == EBADF && "expected errno to have EBADF at this point!");
212 
213  if (NullFD < 0) {
214  if ((NullFD = RetryAfterSignal(-1, ::open, "/dev/null", O_RDWR)) < 0)
215  return std::error_code(errno, std::generic_category());
216  }
217 
218  if (NullFD == StandardFD)
219  FDC.keepOpen();
220  else if (dup2(NullFD, StandardFD) < 0)
221  return std::error_code(errno, std::generic_category());
222  }
223  return std::error_code();
224 }
225 
226 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
227  // Create a signal set filled with *all* signals.
228  sigset_t FullSet;
229  if (sigfillset(&FullSet) < 0)
230  return std::error_code(errno, std::generic_category());
231  // Atomically swap our current signal mask with a full mask.
232  sigset_t SavedSet;
233 #if LLVM_ENABLE_THREADS
234  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
235  return std::error_code(EC, std::generic_category());
236 #else
237  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
238  return std::error_code(errno, std::generic_category());
239 #endif
240  // Attempt to close the file descriptor.
241  // We need to save the error, if one occurs, because our subsequent call to
242  // pthread_sigmask might tamper with errno.
243  int ErrnoFromClose = 0;
244  if (::close(FD) < 0)
245  ErrnoFromClose = errno;
246  // Restore the signal mask back to what we saved earlier.
247  int EC = 0;
248 #if LLVM_ENABLE_THREADS
249  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
250 #else
251  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
252  EC = errno;
253 #endif
254  // The error code from close takes precedence over the one from
255  // pthread_sigmask.
256  if (ErrnoFromClose)
257  return std::error_code(ErrnoFromClose, std::generic_category());
258  return std::error_code(EC, std::generic_category());
259 }
260 
262  return FileDescriptorIsDisplayed(STDIN_FILENO);
263 }
264 
266  return FileDescriptorIsDisplayed(STDOUT_FILENO);
267 }
268 
270  return FileDescriptorIsDisplayed(STDERR_FILENO);
271 }
272 
274 #if HAVE_ISATTY
275  return isatty(fd);
276 #else
277  // If we don't have isatty, just return false.
278  return false;
279 #endif
280 }
281 
282 static unsigned getColumns(int FileID) {
283  // If COLUMNS is defined in the environment, wrap to that many columns.
284  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
285  int Columns = std::atoi(ColumnsStr);
286  if (Columns > 0)
287  return Columns;
288  }
289 
290  unsigned Columns = 0;
291 
292 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
293  // Try to determine the width of the terminal.
294  struct winsize ws;
295  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
296  Columns = ws.ws_col;
297 #endif
298 
299  return Columns;
300 }
301 
302 unsigned Process::StandardOutColumns() {
303  if (!StandardOutIsDisplayed())
304  return 0;
305 
306  return getColumns(1);
307 }
308 
309 unsigned Process::StandardErrColumns() {
310  if (!StandardErrIsDisplayed())
311  return 0;
312 
313  return getColumns(2);
314 }
315 
316 #ifdef HAVE_TERMINFO
317 // We manually declare these extern functions because finding the correct
318 // headers from various terminfo, curses, or other sources is harder than
319 // writing their specs down.
320 extern "C" int setupterm(char *term, int filedes, int *errret);
321 extern "C" struct term *set_curterm(struct term *termp);
322 extern "C" int del_curterm(struct term *termp);
323 extern "C" int tigetnum(char *capname);
324 #endif
325 
326 #ifdef HAVE_TERMINFO
327 static ManagedStatic<sys::Mutex> TermColorMutex;
328 #endif
329 
330 static bool terminalHasColors(int fd) {
331 #ifdef HAVE_TERMINFO
332  // First, acquire a global lock because these C routines are thread hostile.
333  MutexGuard G(*TermColorMutex);
334 
335  int errret = 0;
336  if (setupterm(nullptr, fd, &errret) != 0)
337  // Regardless of why, if we can't get terminfo, we shouldn't try to print
338  // colors.
339  return false;
340 
341  // Test whether the terminal as set up supports color output. How to do this
342  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
343  // would be nice to avoid a dependency on curses proper when we can make do
344  // with a minimal terminfo parsing library. Also, we don't really care whether
345  // the terminal supports the curses-specific color changing routines, merely
346  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
347  // strategy here is just to query the baseline colors capability and if it
348  // supports colors at all to assume it will translate the escape codes into
349  // whatever range of colors it does support. We can add more detailed tests
350  // here if users report them as necessary.
351  //
352  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
353  // the terminfo says that no colors are supported.
354  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
355 
356  // Now extract the structure allocated by setupterm and free its memory
357  // through a really silly dance.
358  struct term *termp = set_curterm(nullptr);
359  (void)del_curterm(termp); // Drop any errors here.
360 
361  // Return true if we found a color capabilities for the current terminal.
362  if (HasColors)
363  return true;
364 #else
365  // When the terminfo database is not available, check if the current terminal
366  // is one of terminals that are known to support ANSI color escape codes.
367  if (const char *TermStr = std::getenv("TERM")) {
368  return StringSwitch<bool>(TermStr)
369  .Case("ansi", true)
370  .Case("cygwin", true)
371  .Case("linux", true)
372  .StartsWith("screen", true)
373  .StartsWith("xterm", true)
374  .StartsWith("vt100", true)
375  .StartsWith("rxvt", true)
376  .EndsWith("color", true)
377  .Default(false);
378  }
379 #endif
380 
381  // Otherwise, be conservative.
382  return false;
383 }
384 
386  // A file descriptor has colors if it is displayed and the terminal has
387  // colors.
388  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
389 }
390 
392  return FileDescriptorHasColors(STDOUT_FILENO);
393 }
394 
396  return FileDescriptorHasColors(STDERR_FILENO);
397 }
398 
399 void Process::UseANSIEscapeCodes(bool /*enable*/) {
400  // No effect.
401 }
402 
404  // No, we use ANSI escape sequences.
405  return false;
406 }
407 
408 const char *Process::OutputColor(char code, bool bold, bool bg) {
409  return colorcodes[bg?1:0][bold?1:0][code&7];
410 }
411 
412 const char *Process::OutputBold(bool bg) {
413  return "\033[1m";
414 }
415 
416 const char *Process::OutputReverse() {
417  return "\033[7m";
418 }
419 
420 const char *Process::ResetColor() {
421  return "\033[0m";
422 }
423 
424 #if !HAVE_DECL_ARC4RANDOM
425 static unsigned GetRandomNumberSeed() {
426  // Attempt to get the initial seed from /dev/urandom, if possible.
427  int urandomFD = open("/dev/urandom", O_RDONLY);
428 
429  if (urandomFD != -1) {
430  unsigned seed;
431  // Don't use a buffered read to avoid reading more data
432  // from /dev/urandom than we need.
433  int count = read(urandomFD, (void *)&seed, sizeof(seed));
434 
435  close(urandomFD);
436 
437  // Return the seed if the read was successful.
438  if (count == sizeof(seed))
439  return seed;
440  }
441 
442  // Otherwise, swizzle the current time and the process ID to form a reasonable
443  // seed.
444  const auto Now = std::chrono::high_resolution_clock::now();
445  return hash_combine(Now.time_since_epoch().count(), ::getpid());
446 }
447 #endif
448 
450 #if HAVE_DECL_ARC4RANDOM
451  return arc4random();
452 #else
453  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
454  (void)x;
455  return ::rand();
456 #endif
457 }
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.
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
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
Definition: StringSwitch.h:203
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(adl_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:974
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
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
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
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & EndsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:78
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:86
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...
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...
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
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:70
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)