1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides the generic Unix implementation of the Process class.
12 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/Hashing.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Mutex.h"
18 #include "llvm/Support/MutexGuard.h"
19 #include "llvm/Support/TimeValue.h"
20 #ifdef HAVE_SYS_TIME_H
23 #ifdef HAVE_SYS_RESOURCE_H
24 #include <sys/resource.h>
26 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
27 // <stdlib.h> instead. Unix.h includes this for us already.
28 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
29 !defined(__OpenBSD__) && !defined(__Bitrig__)
32 #ifdef HAVE_MALLOC_MALLOC_H
33 #include <malloc/malloc.h>
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
42 //===----------------------------------------------------------------------===//
43 //=== WARNING: Implementation here must contain only generic UNIX code that
44 //=== is guaranteed to work on *all* UNIX variants.
45 //===----------------------------------------------------------------------===//
51 process::id_type self_process::get_id() {
55 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
56 #if defined(HAVE_GETRUSAGE)
58 ::getrusage(RUSAGE_SELF, &RU);
59 return std::make_pair(
61 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
62 static_cast<TimeValue::NanoSecondsType>(
63 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
65 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
66 static_cast<TimeValue::NanoSecondsType>(
67 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
69 #warning Cannot get usage times on this platform
70 return std::make_pair(TimeValue(), TimeValue());
74 TimeValue self_process::get_user_time() const {
75 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
76 // Try to get a high resolution CPU timer.
78 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
79 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
80 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
83 // Otherwise fall back to rusage based timing.
84 return getRUsageTimes().first;
87 TimeValue self_process::get_system_time() const {
88 // We can only collect system time by inspecting the results of getrusage.
89 return getRUsageTimes().second;
92 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
93 // offset in mmap(3) should be aligned to the AllocationGranularity.
94 static unsigned getPageSize() {
95 #if defined(HAVE_GETPAGESIZE)
96 const int page_size = ::getpagesize();
97 #elif defined(HAVE_SYSCONF)
98 long page_size = ::sysconf(_SC_PAGE_SIZE);
100 #warning Cannot get the page size on this machine
102 return static_cast<unsigned>(page_size);
105 // This constructor guaranteed to be run exactly once on a single thread, and
106 // sets up various process invariants that can be queried cheaply from then on.
107 self_process::self_process() : PageSize(getPageSize()) {
111 size_t Process::GetMallocUsage() {
112 #if defined(HAVE_MALLINFO)
116 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
117 malloc_statistics_t Stats;
118 malloc_zone_statistics(malloc_default_zone(), &Stats);
119 return Stats.size_in_use; // darwin
120 #elif defined(HAVE_SBRK)
121 // Note this is only an approximation and more closely resembles
122 // the value returned by mallinfo in the arena field.
123 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
124 char *EndOfMemory = (char*)sbrk(0);
125 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
126 return EndOfMemory - StartOfMemory;
130 #warning Cannot get malloc info on this platform
135 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
136 TimeValue &sys_time) {
137 elapsed = TimeValue::now();
138 llvm::tie(user_time, sys_time) = getRUsageTimes();
141 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
142 #include <mach/mach.h>
145 // Some LLVM programs such as bugpoint produce core files as a normal part of
146 // their operation. To prevent the disk from filling up, this function
147 // does what's necessary to prevent their generation.
148 void Process::PreventCoreFiles() {
151 rlim.rlim_cur = rlim.rlim_max = 0;
152 setrlimit(RLIMIT_CORE, &rlim);
155 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
156 // Disable crash reporting on Mac OS X 10.0-10.4
158 // get information about the original set of exception ports for the task
159 mach_msg_type_number_t Count = 0;
160 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
161 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
162 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
163 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
165 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
166 &Count, OriginalPorts, OriginalBehaviors,
168 if (err == KERN_SUCCESS) {
169 // replace each with MACH_PORT_NULL.
170 for (unsigned i = 0; i != Count; ++i)
171 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
172 MACH_PORT_NULL, OriginalBehaviors[i],
176 // Disable crash reporting on Mac OS X 10.5
177 signal(SIGABRT, _exit);
178 signal(SIGILL, _exit);
179 signal(SIGFPE, _exit);
180 signal(SIGSEGV, _exit);
181 signal(SIGBUS, _exit);
185 Optional<std::string> Process::GetEnv(StringRef Name) {
186 std::string NameStr = Name.str();
187 const char *Val = ::getenv(NameStr.c_str());
190 return std::string(Val);
193 bool Process::StandardInIsUserInput() {
194 return FileDescriptorIsDisplayed(STDIN_FILENO);
197 bool Process::StandardOutIsDisplayed() {
198 return FileDescriptorIsDisplayed(STDOUT_FILENO);
201 bool Process::StandardErrIsDisplayed() {
202 return FileDescriptorIsDisplayed(STDERR_FILENO);
205 bool Process::FileDescriptorIsDisplayed(int fd) {
209 // If we don't have isatty, just return false.
214 static unsigned getColumns(int FileID) {
215 // If COLUMNS is defined in the environment, wrap to that many columns.
216 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
217 int Columns = std::atoi(ColumnsStr);
222 unsigned Columns = 0;
224 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
225 // Try to determine the width of the terminal.
227 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
234 unsigned Process::StandardOutColumns() {
235 if (!StandardOutIsDisplayed())
238 return getColumns(1);
241 unsigned Process::StandardErrColumns() {
242 if (!StandardErrIsDisplayed())
245 return getColumns(2);
249 // We manually declare these extern functions because finding the correct
250 // headers from various terminfo, curses, or other sources is harder than
251 // writing their specs down.
252 extern "C" int setupterm(char *term, int filedes, int *errret);
253 extern "C" struct term *set_curterm(struct term *termp);
254 extern "C" int del_curterm(struct term *termp);
255 extern "C" int tigetnum(char *capname);
258 static bool terminalHasColors(int fd) {
260 // First, acquire a global lock because these C routines are thread hostile.
265 if (setupterm((char *)0, fd, &errret) != 0)
266 // Regardless of why, if we can't get terminfo, we shouldn't try to print
270 // Test whether the terminal as set up supports color output. How to do this
271 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
272 // would be nice to avoid a dependency on curses proper when we can make do
273 // with a minimal terminfo parsing library. Also, we don't really care whether
274 // the terminal supports the curses-specific color changing routines, merely
275 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
276 // strategy here is just to query the baseline colors capability and if it
277 // supports colors at all to assume it will translate the escape codes into
278 // whatever range of colors it does support. We can add more detailed tests
279 // here if users report them as necessary.
281 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
282 // the terminfo says that no colors are supported.
283 bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
285 // Now extract the structure allocated by setupterm and free its memory
286 // through a really silly dance.
287 struct term *termp = set_curterm((struct term *)0);
288 (void)del_curterm(termp); // Drop any errors here.
290 // Return true if we found a color capabilities for the current terminal.
295 // Otherwise, be conservative.
299 bool Process::FileDescriptorHasColors(int fd) {
300 // A file descriptor has colors if it is displayed and the terminal has
302 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
305 bool Process::StandardOutHasColors() {
306 return FileDescriptorHasColors(STDOUT_FILENO);
309 bool Process::StandardErrHasColors() {
310 return FileDescriptorHasColors(STDERR_FILENO);
313 bool Process::ColorNeedsFlush() {
314 // No, we use ANSI escape sequences.
318 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
320 #define ALLCOLORS(FGBG,BOLD) {\
321 COLOR(FGBG, "0", BOLD),\
322 COLOR(FGBG, "1", BOLD),\
323 COLOR(FGBG, "2", BOLD),\
324 COLOR(FGBG, "3", BOLD),\
325 COLOR(FGBG, "4", BOLD),\
326 COLOR(FGBG, "5", BOLD),\
327 COLOR(FGBG, "6", BOLD),\
328 COLOR(FGBG, "7", BOLD)\
331 static const char colorcodes[2][2][8][10] = {
332 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
333 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
336 const char *Process::OutputColor(char code, bool bold, bool bg) {
337 return colorcodes[bg?1:0][bold?1:0][code&7];
340 const char *Process::OutputBold(bool bg) {
344 const char *Process::OutputReverse() {
348 const char *Process::ResetColor() {
352 #if !defined(HAVE_ARC4RANDOM)
353 static unsigned GetRandomNumberSeed() {
354 // Attempt to get the initial seed from /dev/urandom, if possible.
355 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
357 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
358 ::fclose(RandomSource);
360 // Return the seed if the read was successful.
365 // Otherwise, swizzle the current time and the process ID to form a reasonable
367 TimeValue Now = TimeValue::now();
368 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
372 unsigned llvm::sys::Process::GetRandomNumber() {
373 #if defined(HAVE_ARC4RANDOM)
376 static int x = (::srand(GetRandomNumberSeed()), 0);