LLVM  4.0.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 #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, OpenBSD, and Bitrig 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__) && !defined(__Bitrig__)
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
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  while (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  break;
215  // retry fstat if we got EINTR, otherwise bubble up the failure.
216  if (errno != EINTR)
217  return std::error_code(errno, std::generic_category());
218  }
219  // if fstat succeeds, move on to the next FD.
220  if (!errno)
221  continue;
222  assert(errno == EBADF && "expected errno to have EBADF at this point!");
223 
224  if (NullFD < 0) {
225  while ((NullFD = open("/dev/null", O_RDWR)) < 0) {
226  if (errno == EINTR)
227  continue;
228  return std::error_code(errno, std::generic_category());
229  }
230  }
231 
232  if (NullFD == StandardFD)
233  FDC.keepOpen();
234  else if (dup2(NullFD, StandardFD) < 0)
235  return std::error_code(errno, std::generic_category());
236  }
237  return std::error_code();
238 }
239 
240 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
241  // Create a signal set filled with *all* signals.
242  sigset_t FullSet;
243  if (sigfillset(&FullSet) < 0)
244  return std::error_code(errno, std::generic_category());
245  // Atomically swap our current signal mask with a full mask.
246  sigset_t SavedSet;
247 #if LLVM_ENABLE_THREADS
248  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
249  return std::error_code(EC, std::generic_category());
250 #else
251  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
252  return std::error_code(errno, std::generic_category());
253 #endif
254  // Attempt to close the file descriptor.
255  // We need to save the error, if one occurs, because our subsequent call to
256  // pthread_sigmask might tamper with errno.
257  int ErrnoFromClose = 0;
258  if (::close(FD) < 0)
259  ErrnoFromClose = errno;
260  // Restore the signal mask back to what we saved earlier.
261  int EC = 0;
262 #if LLVM_ENABLE_THREADS
263  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
264 #else
265  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
266  EC = errno;
267 #endif
268  // The error code from close takes precedence over the one from
269  // pthread_sigmask.
270  if (ErrnoFromClose)
271  return std::error_code(ErrnoFromClose, std::generic_category());
272  return std::error_code(EC, std::generic_category());
273 }
274 
276  return FileDescriptorIsDisplayed(STDIN_FILENO);
277 }
278 
280  return FileDescriptorIsDisplayed(STDOUT_FILENO);
281 }
282 
284  return FileDescriptorIsDisplayed(STDERR_FILENO);
285 }
286 
288 #if HAVE_ISATTY
289  return isatty(fd);
290 #else
291  // If we don't have isatty, just return false.
292  return false;
293 #endif
294 }
295 
296 static unsigned getColumns(int FileID) {
297  // If COLUMNS is defined in the environment, wrap to that many columns.
298  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
299  int Columns = std::atoi(ColumnsStr);
300  if (Columns > 0)
301  return Columns;
302  }
303 
304  unsigned Columns = 0;
305 
306 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
307  // Try to determine the width of the terminal.
308  struct winsize ws;
309  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
310  Columns = ws.ws_col;
311 #endif
312 
313  return Columns;
314 }
315 
316 unsigned Process::StandardOutColumns() {
317  if (!StandardOutIsDisplayed())
318  return 0;
319 
320  return getColumns(1);
321 }
322 
323 unsigned Process::StandardErrColumns() {
324  if (!StandardErrIsDisplayed())
325  return 0;
326 
327  return getColumns(2);
328 }
329 
330 #ifdef HAVE_TERMINFO
331 // We manually declare these extern functions because finding the correct
332 // headers from various terminfo, curses, or other sources is harder than
333 // writing their specs down.
334 extern "C" int setupterm(char *term, int filedes, int *errret);
335 extern "C" struct term *set_curterm(struct term *termp);
336 extern "C" int del_curterm(struct term *termp);
337 extern "C" int tigetnum(char *capname);
338 #endif
339 
340 #ifdef HAVE_TERMINFO
341 static ManagedStatic<sys::Mutex> TermColorMutex;
342 #endif
343 
344 static bool terminalHasColors(int fd) {
345 #ifdef HAVE_TERMINFO
346  // First, acquire a global lock because these C routines are thread hostile.
347  MutexGuard G(*TermColorMutex);
348 
349  int errret = 0;
350  if (setupterm((char *)nullptr, fd, &errret) != 0)
351  // Regardless of why, if we can't get terminfo, we shouldn't try to print
352  // colors.
353  return false;
354 
355  // Test whether the terminal as set up supports color output. How to do this
356  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
357  // would be nice to avoid a dependency on curses proper when we can make do
358  // with a minimal terminfo parsing library. Also, we don't really care whether
359  // the terminal supports the curses-specific color changing routines, merely
360  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
361  // strategy here is just to query the baseline colors capability and if it
362  // supports colors at all to assume it will translate the escape codes into
363  // whatever range of colors it does support. We can add more detailed tests
364  // here if users report them as necessary.
365  //
366  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
367  // the terminfo says that no colors are supported.
368  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
369 
370  // Now extract the structure allocated by setupterm and free its memory
371  // through a really silly dance.
372  struct term *termp = set_curterm((struct term *)nullptr);
373  (void)del_curterm(termp); // Drop any errors here.
374 
375  // Return true if we found a color capabilities for the current terminal.
376  if (HasColors)
377  return true;
378 #endif
379 
380  // Otherwise, be conservative.
381  return false;
382 }
383 
385  // A file descriptor has colors if it is displayed and the terminal has
386  // colors.
387  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
388 }
389 
391  return FileDescriptorHasColors(STDOUT_FILENO);
392 }
393 
395  return FileDescriptorHasColors(STDERR_FILENO);
396 }
397 
398 void Process::UseANSIEscapeCodes(bool /*enable*/) {
399  // No effect.
400 }
401 
403  // No, we use ANSI escape sequences.
404  return false;
405 }
406 
407 const char *Process::OutputColor(char code, bool bold, bool bg) {
408  return colorcodes[bg?1:0][bold?1:0][code&7];
409 }
410 
411 const char *Process::OutputBold(bool bg) {
412  return "\033[1m";
413 }
414 
415 const char *Process::OutputReverse() {
416  return "\033[7m";
417 }
418 
419 const char *Process::ResetColor() {
420  return "\033[0m";
421 }
422 
423 #if !HAVE_DECL_ARC4RANDOM
424 static unsigned GetRandomNumberSeed() {
425  // Attempt to get the initial seed from /dev/urandom, if possible.
426  int urandomFD = open("/dev/urandom", O_RDONLY);
427 
428  if (urandomFD != -1) {
429  unsigned seed;
430  // Don't use a buffered read to avoid reading more data
431  // from /dev/urandom than we need.
432  int count = read(urandomFD, (void *)&seed, sizeof(seed));
433 
434  close(urandomFD);
435 
436  // Return the seed if the read was successful.
437  if (count == sizeof(seed))
438  return seed;
439  }
440 
441  // Otherwise, swizzle the current time and the process ID to form a reasonable
442  // seed.
443  const auto Now = std::chrono::high_resolution_clock::now();
444  return hash_combine(Now.time_since_epoch().count(), ::getpid());
445 }
446 #endif
447 
449 #if HAVE_DECL_ARC4RANDOM
450  return arc4random();
451 #else
452  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
453  (void)x;
454  return ::rand();
455 #endif
456 }
size_t i
value_type read(const void *memory)
Read a value of a particular endianness from memory.
Definition: Endian.h:48
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:130
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...
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If zero
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
Function Alias Analysis false
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'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:791
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 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 sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
static bool coreFilesPrevented
Definition: Process.cpp:77
iterator begin() const
Definition: ArrayRef.h:129
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:225
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:392
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:206
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:368
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
static unsigned GetRandomNumber()
Get the result of a process wide random number generator.
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:47
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:63
static Optional< std::string > GetEnv(StringRef name)