LLVM  8.0.1
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  // Call ::open in a lambda to avoid overload resolution in
215  // RetryAfterSignal when open is overloaded, such as in Bionic.
216  auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
217  if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
218  return std::error_code(errno, std::generic_category());
219  }
220 
221  if (NullFD == StandardFD)
222  FDC.keepOpen();
223  else if (dup2(NullFD, StandardFD) < 0)
224  return std::error_code(errno, std::generic_category());
225  }
226  return std::error_code();
227 }
228 
229 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
230  // Create a signal set filled with *all* signals.
231  sigset_t FullSet;
232  if (sigfillset(&FullSet) < 0)
233  return std::error_code(errno, std::generic_category());
234  // Atomically swap our current signal mask with a full mask.
235  sigset_t SavedSet;
236 #if LLVM_ENABLE_THREADS
237  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
238  return std::error_code(EC, std::generic_category());
239 #else
240  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
241  return std::error_code(errno, std::generic_category());
242 #endif
243  // Attempt to close the file descriptor.
244  // We need to save the error, if one occurs, because our subsequent call to
245  // pthread_sigmask might tamper with errno.
246  int ErrnoFromClose = 0;
247  if (::close(FD) < 0)
248  ErrnoFromClose = errno;
249  // Restore the signal mask back to what we saved earlier.
250  int EC = 0;
251 #if LLVM_ENABLE_THREADS
252  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
253 #else
254  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
255  EC = errno;
256 #endif
257  // The error code from close takes precedence over the one from
258  // pthread_sigmask.
259  if (ErrnoFromClose)
260  return std::error_code(ErrnoFromClose, std::generic_category());
261  return std::error_code(EC, std::generic_category());
262 }
263 
265  return FileDescriptorIsDisplayed(STDIN_FILENO);
266 }
267 
269  return FileDescriptorIsDisplayed(STDOUT_FILENO);
270 }
271 
273  return FileDescriptorIsDisplayed(STDERR_FILENO);
274 }
275 
277 #if HAVE_ISATTY
278  return isatty(fd);
279 #else
280  // If we don't have isatty, just return false.
281  return false;
282 #endif
283 }
284 
285 static unsigned getColumns(int FileID) {
286  // If COLUMNS is defined in the environment, wrap to that many columns.
287  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
288  int Columns = std::atoi(ColumnsStr);
289  if (Columns > 0)
290  return Columns;
291  }
292 
293  unsigned Columns = 0;
294 
295 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
296  // Try to determine the width of the terminal.
297  struct winsize ws;
298  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
299  Columns = ws.ws_col;
300 #endif
301 
302  return Columns;
303 }
304 
305 unsigned Process::StandardOutColumns() {
306  if (!StandardOutIsDisplayed())
307  return 0;
308 
309  return getColumns(1);
310 }
311 
312 unsigned Process::StandardErrColumns() {
313  if (!StandardErrIsDisplayed())
314  return 0;
315 
316  return getColumns(2);
317 }
318 
319 #ifdef HAVE_TERMINFO
320 // We manually declare these extern functions because finding the correct
321 // headers from various terminfo, curses, or other sources is harder than
322 // writing their specs down.
323 extern "C" int setupterm(char *term, int filedes, int *errret);
324 extern "C" struct term *set_curterm(struct term *termp);
325 extern "C" int del_curterm(struct term *termp);
326 extern "C" int tigetnum(char *capname);
327 #endif
328 
329 #ifdef HAVE_TERMINFO
330 static ManagedStatic<sys::Mutex> TermColorMutex;
331 #endif
332 
333 static bool terminalHasColors(int fd) {
334 #ifdef HAVE_TERMINFO
335  // First, acquire a global lock because these C routines are thread hostile.
336  MutexGuard G(*TermColorMutex);
337 
338  int errret = 0;
339  if (setupterm(nullptr, fd, &errret) != 0)
340  // Regardless of why, if we can't get terminfo, we shouldn't try to print
341  // colors.
342  return false;
343 
344  // Test whether the terminal as set up supports color output. How to do this
345  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
346  // would be nice to avoid a dependency on curses proper when we can make do
347  // with a minimal terminfo parsing library. Also, we don't really care whether
348  // the terminal supports the curses-specific color changing routines, merely
349  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
350  // strategy here is just to query the baseline colors capability and if it
351  // supports colors at all to assume it will translate the escape codes into
352  // whatever range of colors it does support. We can add more detailed tests
353  // here if users report them as necessary.
354  //
355  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
356  // the terminfo says that no colors are supported.
357  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
358 
359  // Now extract the structure allocated by setupterm and free its memory
360  // through a really silly dance.
361  struct term *termp = set_curterm(nullptr);
362  (void)del_curterm(termp); // Drop any errors here.
363 
364  // Return true if we found a color capabilities for the current terminal.
365  if (HasColors)
366  return true;
367 #else
368  // When the terminfo database is not available, check if the current terminal
369  // is one of terminals that are known to support ANSI color escape codes.
370  if (const char *TermStr = std::getenv("TERM")) {
371  return StringSwitch<bool>(TermStr)
372  .Case("ansi", true)
373  .Case("cygwin", true)
374  .Case("linux", true)
375  .StartsWith("screen", true)
376  .StartsWith("xterm", true)
377  .StartsWith("vt100", true)
378  .StartsWith("rxvt", true)
379  .EndsWith("color", true)
380  .Default(false);
381  }
382 #endif
383 
384  // Otherwise, be conservative.
385  return false;
386 }
387 
389  // A file descriptor has colors if it is displayed and the terminal has
390  // colors.
391  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
392 }
393 
395  return FileDescriptorHasColors(STDOUT_FILENO);
396 }
397 
399  return FileDescriptorHasColors(STDERR_FILENO);
400 }
401 
402 void Process::UseANSIEscapeCodes(bool /*enable*/) {
403  // No effect.
404 }
405 
407  // No, we use ANSI escape sequences.
408  return false;
409 }
410 
411 const char *Process::OutputColor(char code, bool bold, bool bg) {
412  return colorcodes[bg?1:0][bold?1:0][code&7];
413 }
414 
415 const char *Process::OutputBold(bool bg) {
416  return "\033[1m";
417 }
418 
419 const char *Process::OutputReverse() {
420  return "\033[7m";
421 }
422 
423 const char *Process::ResetColor() {
424  return "\033[0m";
425 }
426 
427 #if !HAVE_DECL_ARC4RANDOM
428 static unsigned GetRandomNumberSeed() {
429  // Attempt to get the initial seed from /dev/urandom, if possible.
430  int urandomFD = open("/dev/urandom", O_RDONLY);
431 
432  if (urandomFD != -1) {
433  unsigned seed;
434  // Don't use a buffered read to avoid reading more data
435  // from /dev/urandom than we need.
436  int count = read(urandomFD, (void *)&seed, sizeof(seed));
437 
438  close(urandomFD);
439 
440  // Return the seed if the read was successful.
441  if (count == sizeof(seed))
442  return seed;
443  }
444 
445  // Otherwise, swizzle the current time and the process ID to form a reasonable
446  // seed.
447  const auto Now = std::chrono::high_resolution_clock::now();
448  return hash_combine(Now.time_since_epoch().count(), ::getpid());
449 }
450 #endif
451 
453 #if HAVE_DECL_ARC4RANDOM
454  return arc4random();
455 #else
456  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
457  (void)x;
458  return ::rand();
459 #endif
460 }
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:228
This class represents lattice values for constants.
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()
amdgpu Simplify well known AMD library false Value Value const Twine & Name
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:81
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:1252
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:88
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:601
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)