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. 10// 11//===----------------------------------------------------------------------===// 12 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 <mutex> 19#if HAVE_FCNTL_H 20#include <fcntl.h> 21#endif 22#ifdef HAVE_SYS_TIME_H 23#include <sys/time.h> 24#endif 25#ifdef HAVE_SYS_RESOURCE_H 26#include <sys/resource.h> 27#endif 28#ifdef HAVE_SYS_STAT_H 29#include <sys/stat.h> 30#endif 31#if HAVE_SIGNAL_H 32#include <signal.h> 33#endif 34#if defined(HAVE_MALLINFO) 35#include <malloc.h> 36#endif 37#if defined(HAVE_MALLCTL) 38#include <malloc_np.h> 39#endif 40#ifdef HAVE_MALLOC_MALLOC_H 41#include <malloc/malloc.h> 42#endif 43#ifdef HAVE_SYS_IOCTL_H 44# include <sys/ioctl.h> 45#endif 46#ifdef HAVE_TERMIOS_H 47# include <termios.h> 48#endif 49 50//===----------------------------------------------------------------------===// 51//=== WARNING: Implementation here must contain only generic UNIX code that 52//=== is guaranteed to work on *all* UNIX variants. 53//===----------------------------------------------------------------------===// 54 55using namespace llvm; 56using namespace sys; 57 58static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() { 59#if defined(HAVE_GETRUSAGE) 60 struct rusage RU; 61 ::getrusage(RUSAGE_SELF, &RU); 62 return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) }; 63#else 64#warning Cannot get usage times on this platform 65 return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() }; 66#endif 67} 68 69Process::Pid Process::getProcessId() { 70 static_assert(sizeof(Pid) >= sizeof(pid_t), 71 "Process::Pid should be big enough to store pid_t"); 72 return Pid(::getpid()); 73} 74 75// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and 76// offset in mmap(3) should be aligned to the AllocationGranularity. 77Expected<unsigned> Process::getPageSize() { 78#if defined(HAVE_GETPAGESIZE) 79 static const int page_size = ::getpagesize(); 80#elif defined(HAVE_SYSCONF) 81 static long page_size = ::sysconf(_SC_PAGE_SIZE); 82#else 83#error Cannot get the page size on this machine 84#endif 85 if (page_size == -1) 86 return errorCodeToError(std::error_code(errno, std::generic_category())); 87 88 return static_cast<unsigned>(page_size); 89} 90 91size_t Process::GetMallocUsage() { 92#if defined(HAVE_MALLINFO) 93 struct mallinfo mi; 94 mi = ::mallinfo(); 95 return mi.uordblks; 96#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) 97 malloc_statistics_t Stats; 98 malloc_zone_statistics(malloc_default_zone(), &Stats); 99 return Stats.size_in_use; // darwin 100#elif defined(HAVE_MALLCTL) 101 size_t alloc, sz; 102 sz = sizeof(size_t); 103 if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0) 104 return alloc; 105 return 0; 106#elif defined(HAVE_SBRK) 107 // Note this is only an approximation and more closely resembles 108 // the value returned by mallinfo in the arena field. 109 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0)); 110 char *EndOfMemory = (char*)sbrk(0); 111 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1)) 112 return EndOfMemory - StartOfMemory; 113 return 0; 114#else 115#warning Cannot get malloc info on this platform 116 return 0; 117#endif 118} 119 120void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, 121 std::chrono::nanoseconds &sys_time) { 122 elapsed = std::chrono::system_clock::now(); 123 std::tie(user_time, sys_time) = getRUsageTimes(); 124} 125 126#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__) 127#include <mach/mach.h> 128#endif 129 130// Some LLVM programs such as bugpoint produce core files as a normal part of 131// their operation. To prevent the disk from filling up, this function 132// does what's necessary to prevent their generation. 133void Process::PreventCoreFiles() { 134#if HAVE_SETRLIMIT 135 struct rlimit rlim; 136 rlim.rlim_cur = rlim.rlim_max = 0; 137 setrlimit(RLIMIT_CORE, &rlim); 138#endif 139 140#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__) 141 // Disable crash reporting on Mac OS X 10.0-10.4 142 143 // get information about the original set of exception ports for the task 144 mach_msg_type_number_t Count = 0; 145 exception_mask_t OriginalMasks[EXC_TYPES_COUNT]; 146 exception_port_t OriginalPorts[EXC_TYPES_COUNT]; 147 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT]; 148 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT]; 149 kern_return_t err = 150 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks, 151 &Count, OriginalPorts, OriginalBehaviors, 152 OriginalFlavors); 153 if (err == KERN_SUCCESS) { 154 // replace each with MACH_PORT_NULL. 155 for (unsigned i = 0; i != Count; ++i) 156 task_set_exception_ports(mach_task_self(), OriginalMasks[i], 157 MACH_PORT_NULL, OriginalBehaviors[i], 158 OriginalFlavors[i]); 159 } 160 161 // Disable crash reporting on Mac OS X 10.5 162 signal(SIGABRT, _exit); 163 signal(SIGILL, _exit); 164 signal(SIGFPE, _exit); 165 signal(SIGSEGV, _exit); 166 signal(SIGBUS, _exit); 167#endif 168 169 coreFilesPrevented = true; 170} 171 172Optional<std::string> Process::GetEnv(StringRef Name) { 173 std::string NameStr = Name.str(); 174 const char *Val = ::getenv(NameStr.c_str()); 175 if (!Val) 176 return None; 177 return std::string(Val); 178} 179 180namespace { 181class FDCloser { 182public: 183 FDCloser(int &FD) : FD(FD), KeepOpen(false) {} 184 void keepOpen() { KeepOpen = true; } 185 ~FDCloser() { 186 if (!KeepOpen && FD >= 0) 187 ::close(FD); 188 } 189 190private: 191 FDCloser(const FDCloser &) = delete; 192 void operator=(const FDCloser &) = delete; 193 194 int &FD; 195 bool KeepOpen; 196}; 197} 198 199std::error_code Process::FixupStandardFileDescriptors() { 200 int NullFD = -1; 201 FDCloser FDC(NullFD); 202 const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; 203 for (int StandardFD : StandardFDs) { 204 struct stat st; 205 errno = 0; 206 if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) { 207 assert(errno && "expected errno to be set if fstat failed!"); 208 // fstat should return EBADF if the file descriptor is closed. 209 if (errno != EBADF) 210 return std::error_code(errno, std::generic_category()); 211 } 212 // if fstat succeeds, move on to the next FD. 213 if (!errno) 214 continue; 215 assert(errno == EBADF && "expected errno to have EBADF at this point!"); 216 217 if (NullFD < 0) { 218 // Call ::open in a lambda to avoid overload resolution in 219 // RetryAfterSignal when open is overloaded, such as in Bionic. 220 auto Open = [&]() { return ::open("/dev/null", O_RDWR); }; 221 if ((NullFD = RetryAfterSignal(-1, Open)) < 0) 222 return std::error_code(errno, std::generic_category()); 223 } 224 225 if (NullFD == StandardFD) 226 FDC.keepOpen(); 227 else if (dup2(NullFD, StandardFD) < 0) 228 return std::error_code(errno, std::generic_category()); 229 } 230 return std::error_code(); 231} 232 233std::error_code Process::SafelyCloseFileDescriptor(int FD) { 234 // Create a signal set filled with *all* signals. 235 sigset_t FullSet; 236 if (sigfillset(&FullSet) < 0) 237 return std::error_code(errno, std::generic_category()); 238 // Atomically swap our current signal mask with a full mask. 239 sigset_t SavedSet; 240#if LLVM_ENABLE_THREADS 241 if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) 242 return std::error_code(EC, std::generic_category()); 243#else 244 if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0) 245 return std::error_code(errno, std::generic_category()); 246#endif 247 // Attempt to close the file descriptor. 248 // We need to save the error, if one occurs, because our subsequent call to 249 // pthread_sigmask might tamper with errno. 250 int ErrnoFromClose = 0; 251 if (::close(FD) < 0) 252 ErrnoFromClose = errno; 253 // Restore the signal mask back to what we saved earlier. 254 int EC = 0; 255#if LLVM_ENABLE_THREADS 256 EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr); 257#else 258 if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0) 259 EC = errno; 260#endif 261 // The error code from close takes precedence over the one from 262 // pthread_sigmask. 263 if (ErrnoFromClose) 264 return std::error_code(ErrnoFromClose, std::generic_category()); 265 return std::error_code(EC, std::generic_category()); 266} 267 268bool Process::StandardInIsUserInput() { 269 return FileDescriptorIsDisplayed(STDIN_FILENO); 270} 271 272bool Process::StandardOutIsDisplayed() { 273 return FileDescriptorIsDisplayed(STDOUT_FILENO); 274} 275 276bool Process::StandardErrIsDisplayed() { 277 return FileDescriptorIsDisplayed(STDERR_FILENO); 278} 279 280bool Process::FileDescriptorIsDisplayed(int fd) { 281#if HAVE_ISATTY 282 return isatty(fd); 283#else 284 // If we don't have isatty, just return false. 285 return false; 286#endif 287} 288 289static unsigned getColumns() { 290 // If COLUMNS is defined in the environment, wrap to that many columns. 291 if (const char *ColumnsStr = std::getenv("COLUMNS")) { 292 int Columns = std::atoi(ColumnsStr); 293 if (Columns > 0) 294 return Columns; 295 } 296 297 // We used to call ioctl TIOCGWINSZ to determine the width. It is considered 298 // unuseful. 299 return 0; 300} 301 302unsigned Process::StandardOutColumns() { 303 if (!StandardOutIsDisplayed()) 304 return 0; 305 306 return getColumns(); 307} 308 309unsigned Process::StandardErrColumns() { 310 if (!StandardErrIsDisplayed()) 311 return 0; 312 313 return getColumns(); 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. 320extern "C" int setupterm(char *term, int filedes, int *errret); 321extern "C" struct term *set_curterm(struct term *termp); 322extern "C" int del_curterm(struct term *termp); 323extern "C" int tigetnum(char *capname); 324#endif 325 326#ifdef HAVE_TERMINFO 327static ManagedStatic<std::mutex> TermColorMutex; 328#endif 329 330static bool terminalHasColors(int fd) { 331#ifdef HAVE_TERMINFO 332 // First, acquire a global lock because these C routines are thread hostile. 333 std::lock_guard<std::mutex> 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 385bool Process::FileDescriptorHasColors(int fd) { 386 // A file descriptor has colors if it is displayed and the terminal has 387 // colors. 388 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd); 389} 390 391bool Process::StandardOutHasColors() { 392 return FileDescriptorHasColors(STDOUT_FILENO); 393} 394 395bool Process::StandardErrHasColors() { 396 return FileDescriptorHasColors(STDERR_FILENO); 397} 398 399void Process::UseANSIEscapeCodes(bool /*enable*/) { 400 // No effect. 401} 402 403bool Process::ColorNeedsFlush() { 404 // No, we use ANSI escape sequences. 405 return false; 406} 407 408const char *Process::OutputColor(char code, bool bold, bool bg) { 409 return colorcodes[bg?1:0][bold?1:0][code&7]; 410} 411 412const char *Process::OutputBold(bool bg) { 413 return "\033[1m"; 414} 415 416const char *Process::OutputReverse() { 417 return "\033[7m"; 418} 419 420const char *Process::ResetColor() { 421 return "\033[0m"; 422} 423 424#if !HAVE_DECL_ARC4RANDOM 425static 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 449unsigned llvm::sys::Process::GetRandomNumber() { 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} 458