Home | History | Annotate | Download | only in Unix
      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"
     18 #include "llvm/Support/ManagedStatic.h"
     19 #include "llvm/Support/Mutex.h"
     20 #include "llvm/Support/MutexGuard.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.
    129 void Process::PreventCoreFiles() {
    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 
    168 Optional<std::string> Process::GetEnv(StringRef Name) {
    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 
    264 bool Process::StandardInIsUserInput() {
    265   return FileDescriptorIsDisplayed(STDIN_FILENO);
    266 }
    267 
    268 bool Process::StandardOutIsDisplayed() {
    269   return FileDescriptorIsDisplayed(STDOUT_FILENO);
    270 }
    271 
    272 bool Process::StandardErrIsDisplayed() {
    273   return FileDescriptorIsDisplayed(STDERR_FILENO);
    274 }
    275 
    276 bool Process::FileDescriptorIsDisplayed(int fd) {
    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 
    388 bool Process::FileDescriptorHasColors(int fd) {
    389   // A file descriptor has colors if it is displayed and the terminal has
    390   // colors.
    391   return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
    392 }
    393 
    394 bool Process::StandardOutHasColors() {
    395   return FileDescriptorHasColors(STDOUT_FILENO);
    396 }
    397 
    398 bool Process::StandardErrHasColors() {
    399   return FileDescriptorHasColors(STDERR_FILENO);
    400 }
    401 
    402 void Process::UseANSIEscapeCodes(bool /*enable*/) {
    403   // No effect.
    404 }
    405 
    406 bool Process::ColorNeedsFlush() {
    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 
    452 unsigned llvm::sys::Process::GetRandomNumber() {
    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 }
    461