[llvm-exegesis] [NFC] Fixing typo.
[llvm-complete.git] / lib / Support / Unix / Process.inc
blob7c834f9711469405c932827868e5163eaa2c56b2
1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides the generic Unix implementation of the Process class.
11 //===----------------------------------------------------------------------===//
13 #include "Unix.h"
14 #include "llvm/ADT/Hashing.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Config/config.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/Mutex.h"
19 #include "llvm/Support/MutexGuard.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 #if defined(HAVE_MALLINFO)
36 #include <malloc.h>
37 #endif
38 #if defined(HAVE_MALLCTL)
39 #include <malloc_np.h>
40 #endif
41 #ifdef HAVE_MALLOC_MALLOC_H
42 #include <malloc/malloc.h>
43 #endif
44 #ifdef HAVE_SYS_IOCTL_H
45 #  include <sys/ioctl.h>
46 #endif
47 #ifdef HAVE_TERMIOS_H
48 #  include <termios.h>
49 #endif
51 //===----------------------------------------------------------------------===//
52 //=== WARNING: Implementation here must contain only generic UNIX code that
53 //===          is guaranteed to work on *all* UNIX variants.
54 //===----------------------------------------------------------------------===//
56 using namespace llvm;
57 using namespace sys;
59 static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
60 #if defined(HAVE_GETRUSAGE)
61   struct rusage RU;
62   ::getrusage(RUSAGE_SELF, &RU);
63   return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
64 #else
65 #warning Cannot get usage times on this platform
66   return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() };
67 #endif
70 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
71 // offset in mmap(3) should be aligned to the AllocationGranularity.
72 unsigned Process::getPageSize() {
73 #if defined(HAVE_GETPAGESIZE)
74   static const int page_size = ::getpagesize();
75 #elif defined(HAVE_SYSCONF)
76   static long page_size = ::sysconf(_SC_PAGE_SIZE);
77 #else
78 #error Cannot get the page size on this machine
79 #endif
80   return static_cast<unsigned>(page_size);
83 size_t Process::GetMallocUsage() {
84 #if defined(HAVE_MALLINFO)
85   struct mallinfo mi;
86   mi = ::mallinfo();
87   return mi.uordblks;
88 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
89   malloc_statistics_t Stats;
90   malloc_zone_statistics(malloc_default_zone(), &Stats);
91   return Stats.size_in_use;   // darwin
92 #elif defined(HAVE_MALLCTL)
93   size_t alloc, sz;
94   sz = sizeof(size_t);
95   if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
96     return alloc;
97   return 0;
98 #elif defined(HAVE_SBRK)
99   // Note this is only an approximation and more closely resembles
100   // the value returned by mallinfo in the arena field.
101   static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
102   char *EndOfMemory = (char*)sbrk(0);
103   if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
104     return EndOfMemory - StartOfMemory;
105   return 0;
106 #else
107 #warning Cannot get malloc info on this platform
108   return 0;
109 #endif
112 void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
113                            std::chrono::nanoseconds &sys_time) {
114   elapsed = std::chrono::system_clock::now();
115   std::tie(user_time, sys_time) = getRUsageTimes();
118 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
119 #include <mach/mach.h>
120 #endif
122 // Some LLVM programs such as bugpoint produce core files as a normal part of
123 // their operation. To prevent the disk from filling up, this function
124 // does what's necessary to prevent their generation.
125 void Process::PreventCoreFiles() {
126 #if HAVE_SETRLIMIT
127   struct rlimit rlim;
128   rlim.rlim_cur = rlim.rlim_max = 0;
129   setrlimit(RLIMIT_CORE, &rlim);
130 #endif
132 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
133   // Disable crash reporting on Mac OS X 10.0-10.4
135   // get information about the original set of exception ports for the task
136   mach_msg_type_number_t Count = 0;
137   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
138   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
139   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
140   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
141   kern_return_t err =
142     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
143                              &Count, OriginalPorts, OriginalBehaviors,
144                              OriginalFlavors);
145   if (err == KERN_SUCCESS) {
146     // replace each with MACH_PORT_NULL.
147     for (unsigned i = 0; i != Count; ++i)
148       task_set_exception_ports(mach_task_self(), OriginalMasks[i],
149                                MACH_PORT_NULL, OriginalBehaviors[i],
150                                OriginalFlavors[i]);
151   }
153   // Disable crash reporting on Mac OS X 10.5
154   signal(SIGABRT, _exit);
155   signal(SIGILL,  _exit);
156   signal(SIGFPE,  _exit);
157   signal(SIGSEGV, _exit);
158   signal(SIGBUS,  _exit);
159 #endif
161   coreFilesPrevented = true;
164 Optional<std::string> Process::GetEnv(StringRef Name) {
165   std::string NameStr = Name.str();
166   const char *Val = ::getenv(NameStr.c_str());
167   if (!Val)
168     return None;
169   return std::string(Val);
172 namespace {
173 class FDCloser {
174 public:
175   FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
176   void keepOpen() { KeepOpen = true; }
177   ~FDCloser() {
178     if (!KeepOpen && FD >= 0)
179       ::close(FD);
180   }
182 private:
183   FDCloser(const FDCloser &) = delete;
184   void operator=(const FDCloser &) = delete;
186   int &FD;
187   bool KeepOpen;
191 std::error_code Process::FixupStandardFileDescriptors() {
192   int NullFD = -1;
193   FDCloser FDC(NullFD);
194   const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
195   for (int StandardFD : StandardFDs) {
196     struct stat st;
197     errno = 0;
198     if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
199       assert(errno && "expected errno to be set if fstat failed!");
200       // fstat should return EBADF if the file descriptor is closed.
201       if (errno != EBADF)
202         return std::error_code(errno, std::generic_category());
203     }
204     // if fstat succeeds, move on to the next FD.
205     if (!errno)
206       continue;
207     assert(errno == EBADF && "expected errno to have EBADF at this point!");
209     if (NullFD < 0) {
210       // Call ::open in a lambda to avoid overload resolution in
211       // RetryAfterSignal when open is overloaded, such as in Bionic.
212       auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
213       if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
214         return std::error_code(errno, std::generic_category());
215     }
217     if (NullFD == StandardFD)
218       FDC.keepOpen();
219     else if (dup2(NullFD, StandardFD) < 0)
220       return std::error_code(errno, std::generic_category());
221   }
222   return std::error_code();
225 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
226   // Create a signal set filled with *all* signals.
227   sigset_t FullSet;
228   if (sigfillset(&FullSet) < 0)
229     return std::error_code(errno, std::generic_category());
230   // Atomically swap our current signal mask with a full mask.
231   sigset_t SavedSet;
232 #if LLVM_ENABLE_THREADS
233   if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
234     return std::error_code(EC, std::generic_category());
235 #else
236   if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
237     return std::error_code(errno, std::generic_category());
238 #endif
239   // Attempt to close the file descriptor.
240   // We need to save the error, if one occurs, because our subsequent call to
241   // pthread_sigmask might tamper with errno.
242   int ErrnoFromClose = 0;
243   if (::close(FD) < 0)
244     ErrnoFromClose = errno;
245   // Restore the signal mask back to what we saved earlier.
246   int EC = 0;
247 #if LLVM_ENABLE_THREADS
248   EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
249 #else
250   if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
251     EC = errno;
252 #endif
253   // The error code from close takes precedence over the one from
254   // pthread_sigmask.
255   if (ErrnoFromClose)
256     return std::error_code(ErrnoFromClose, std::generic_category());
257   return std::error_code(EC, std::generic_category());
260 bool Process::StandardInIsUserInput() {
261   return FileDescriptorIsDisplayed(STDIN_FILENO);
264 bool Process::StandardOutIsDisplayed() {
265   return FileDescriptorIsDisplayed(STDOUT_FILENO);
268 bool Process::StandardErrIsDisplayed() {
269   return FileDescriptorIsDisplayed(STDERR_FILENO);
272 bool Process::FileDescriptorIsDisplayed(int fd) {
273 #if HAVE_ISATTY
274   return isatty(fd);
275 #else
276   // If we don't have isatty, just return false.
277   return false;
278 #endif
281 static unsigned getColumns(int FileID) {
282   // If COLUMNS is defined in the environment, wrap to that many columns.
283   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
284     int Columns = std::atoi(ColumnsStr);
285     if (Columns > 0)
286       return Columns;
287   }
289   unsigned Columns = 0;
291 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
292   // Try to determine the width of the terminal.
293   struct winsize ws;
294   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
295     Columns = ws.ws_col;
296 #endif
298   return Columns;
301 unsigned Process::StandardOutColumns() {
302   if (!StandardOutIsDisplayed())
303     return 0;
305   return getColumns(1);
308 unsigned Process::StandardErrColumns() {
309   if (!StandardErrIsDisplayed())
310     return 0;
312   return getColumns(2);
315 #ifdef HAVE_TERMINFO
316 // We manually declare these extern functions because finding the correct
317 // headers from various terminfo, curses, or other sources is harder than
318 // writing their specs down.
319 extern "C" int setupterm(char *term, int filedes, int *errret);
320 extern "C" struct term *set_curterm(struct term *termp);
321 extern "C" int del_curterm(struct term *termp);
322 extern "C" int tigetnum(char *capname);
323 #endif
325 #ifdef HAVE_TERMINFO
326 static ManagedStatic<sys::Mutex> TermColorMutex;
327 #endif
329 static bool terminalHasColors(int fd) {
330 #ifdef HAVE_TERMINFO
331   // First, acquire a global lock because these C routines are thread hostile.
332   MutexGuard G(*TermColorMutex);
334   int errret = 0;
335   if (setupterm(nullptr, fd, &errret) != 0)
336     // Regardless of why, if we can't get terminfo, we shouldn't try to print
337     // colors.
338     return false;
340   // Test whether the terminal as set up supports color output. How to do this
341   // isn't entirely obvious. We can use the curses routine 'has_colors' but it
342   // would be nice to avoid a dependency on curses proper when we can make do
343   // with a minimal terminfo parsing library. Also, we don't really care whether
344   // the terminal supports the curses-specific color changing routines, merely
345   // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
346   // strategy here is just to query the baseline colors capability and if it
347   // supports colors at all to assume it will translate the escape codes into
348   // whatever range of colors it does support. We can add more detailed tests
349   // here if users report them as necessary.
350   //
351   // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
352   // the terminfo says that no colors are supported.
353   bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
355   // Now extract the structure allocated by setupterm and free its memory
356   // through a really silly dance.
357   struct term *termp = set_curterm(nullptr);
358   (void)del_curterm(termp); // Drop any errors here.
360   // Return true if we found a color capabilities for the current terminal.
361   if (HasColors)
362     return true;
363 #else
364   // When the terminfo database is not available, check if the current terminal
365   // is one of terminals that are known to support ANSI color escape codes.
366   if (const char *TermStr = std::getenv("TERM")) {
367     return StringSwitch<bool>(TermStr)
368       .Case("ansi", true)
369       .Case("cygwin", true)
370       .Case("linux", true)
371       .StartsWith("screen", true)
372       .StartsWith("xterm", true)
373       .StartsWith("vt100", true)
374       .StartsWith("rxvt", true)
375       .EndsWith("color", true)
376       .Default(false);
377   }
378 #endif
380   // Otherwise, be conservative.
381   return false;
384 bool Process::FileDescriptorHasColors(int fd) {
385   // A file descriptor has colors if it is displayed and the terminal has
386   // colors.
387   return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
390 bool Process::StandardOutHasColors() {
391   return FileDescriptorHasColors(STDOUT_FILENO);
394 bool Process::StandardErrHasColors() {
395   return FileDescriptorHasColors(STDERR_FILENO);
398 void Process::UseANSIEscapeCodes(bool /*enable*/) {
399   // No effect.
402 bool Process::ColorNeedsFlush() {
403   // No, we use ANSI escape sequences.
404   return false;
407 const char *Process::OutputColor(char code, bool bold, bool bg) {
408   return colorcodes[bg?1:0][bold?1:0][code&7];
411 const char *Process::OutputBold(bool bg) {
412   return "\033[1m";
415 const char *Process::OutputReverse() {
416   return "\033[7m";
419 const char *Process::ResetColor() {
420   return "\033[0m";
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);
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));
434     close(urandomFD);
436     // Return the seed if the read was successful.
437     if (count == sizeof(seed))
438       return seed;
439   }
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());
446 #endif
448 unsigned llvm::sys::Process::GetRandomNumber() {
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