blob: 47d0a3c794d4d4fdb337286debcda08f50bd54ce [file] [log] [blame]
Reid Spencer33b9d772004-09-11 04:56:56 +00001//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
Michael J. Spencer447762d2010-11-29 18:16:10 +00002//
Reid Spencer33b9d772004-09-11 04:56:56 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Michael J. Spencer447762d2010-11-29 18:16:10 +00007//
Reid Spencer33b9d772004-09-11 04:56:56 +00008//===----------------------------------------------------------------------===//
9//
10// This file provides the generic Unix implementation of the Process class.
11//
12//===----------------------------------------------------------------------===//
13
Reid Spencerac38f3a2004-12-20 00:59:28 +000014#include "Unix.h"
Daniel Dunbar5f1c9562012-05-08 20:38:00 +000015#include "llvm/ADT/Hashing.h"
Chandler Carruthcad7e5e2013-08-07 08:47:36 +000016#include "llvm/Support/Mutex.h"
17#include "llvm/Support/MutexGuard.h"
Daniel Dunbar5f1c9562012-05-08 20:38:00 +000018#include "llvm/Support/TimeValue.h"
Reid Spencerac38f3a2004-12-20 00:59:28 +000019#ifdef HAVE_SYS_TIME_H
20#include <sys/time.h>
21#endif
22#ifdef HAVE_SYS_RESOURCE_H
23#include <sys/resource.h>
24#endif
Eric Christopher22738d02012-08-06 20:52:18 +000025// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
26// <stdlib.h> instead. Unix.h includes this for us already.
27#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
28 !defined(__OpenBSD__) && !defined(__Bitrig__)
Reid Spencerac38f3a2004-12-20 00:59:28 +000029#include <malloc.h>
30#endif
Chris Lattner698fa762005-11-14 07:00:29 +000031#ifdef HAVE_MALLOC_MALLOC_H
32#include <malloc/malloc.h>
33#endif
Douglas Gregor15436612009-05-11 18:05:52 +000034#ifdef HAVE_SYS_IOCTL_H
35# include <sys/ioctl.h>
36#endif
Douglas Gregorb81294d2009-05-18 17:21:34 +000037#ifdef HAVE_TERMIOS_H
38# include <termios.h>
39#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000040
41//===----------------------------------------------------------------------===//
42//=== WARNING: Implementation here must contain only generic UNIX code that
43//=== is guaranteed to work on *all* UNIX variants.
44//===----------------------------------------------------------------------===//
45
Chris Lattner2f107cf2006-09-14 06:01:41 +000046using namespace llvm;
Reid Spencer33b9d772004-09-11 04:56:56 +000047using namespace sys;
48
Chandler Carruth97683aa2012-12-31 11:17:50 +000049
50process::id_type self_process::get_id() {
51 return getpid();
52}
53
Chandler Carruthef7f9682013-01-04 23:19:55 +000054static std::pair<TimeValue, TimeValue> getRUsageTimes() {
55#if defined(HAVE_GETRUSAGE)
56 struct rusage RU;
57 ::getrusage(RUSAGE_SELF, &RU);
58 return std::make_pair(
59 TimeValue(
60 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
61 static_cast<TimeValue::NanoSecondsType>(
62 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
63 TimeValue(
64 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
65 static_cast<TimeValue::NanoSecondsType>(
66 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
67#else
68#warning Cannot get usage times on this platform
69 return std::make_pair(TimeValue(), TimeValue());
70#endif
71}
72
73TimeValue self_process::get_user_time() const {
Chandler Carruthb5429f42013-01-05 00:42:50 +000074#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
Chandler Carruthef7f9682013-01-04 23:19:55 +000075 // Try to get a high resolution CPU timer.
76 struct timespec TS;
77 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
78 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
79 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
80#endif
81
82 // Otherwise fall back to rusage based timing.
83 return getRUsageTimes().first;
84}
85
86TimeValue self_process::get_system_time() const {
87 // We can only collect system time by inspecting the results of getrusage.
88 return getRUsageTimes().second;
89}
90
NAKAMURA Takumi7a042342013-09-04 14:12:26 +000091// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
92// offset in mmap(3) should be aligned to the AllocationGranularity.
Chandler Carruth15dcad92012-12-31 23:23:35 +000093static unsigned getPageSize() {
NAKAMURA Takumi3bbbe2e2013-08-21 13:47:12 +000094#if defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000095 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000096#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +000097 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +000098#else
99#warning Cannot get the page size on this machine
100#endif
Reid Spencer33b9d772004-09-11 04:56:56 +0000101 return static_cast<unsigned>(page_size);
102}
103
Chandler Carruth15dcad92012-12-31 23:23:35 +0000104// This constructor guaranteed to be run exactly once on a single thread, and
105// sets up various process invariants that can be queried cheaply from then on.
106self_process::self_process() : PageSize(getPageSize()) {
107}
108
109
Chris Lattner698fa762005-11-14 07:00:29 +0000110size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000111#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000112 struct mallinfo mi;
113 mi = ::mallinfo();
114 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000115#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
116 malloc_statistics_t Stats;
117 malloc_zone_statistics(malloc_default_zone(), &Stats);
118 return Stats.size_in_use; // darwin
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000119#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000120 // Note this is only an approximation and more closely resembles
121 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +0000122 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
123 char *EndOfMemory = (char*)sbrk(0);
124 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
125 return EndOfMemory - StartOfMemory;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000126 else
127 return 0;
128#else
129#warning Cannot get malloc info on this platform
130 return 0;
131#endif
132}
133
Chandler Carruthef7f9682013-01-04 23:19:55 +0000134void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
135 TimeValue &sys_time) {
Reid Spencerac38f3a2004-12-20 00:59:28 +0000136 elapsed = TimeValue::now();
Chandler Carruthef7f9682013-01-04 23:19:55 +0000137 llvm::tie(user_time, sys_time) = getRUsageTimes();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000138}
139
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000140#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000141#include <mach/mach.h>
142#endif
143
Reid Spencercf15b872004-12-27 06:17:27 +0000144// Some LLVM programs such as bugpoint produce core files as a normal part of
145// their operation. To prevent the disk from filling up, this function
146// does what's necessary to prevent their generation.
147void Process::PreventCoreFiles() {
148#if HAVE_SETRLIMIT
149 struct rlimit rlim;
150 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000151 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000152#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000153
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000154#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000155 // Disable crash reporting on Mac OS X 10.0-10.4
156
157 // get information about the original set of exception ports for the task
158 mach_msg_type_number_t Count = 0;
159 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
160 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
161 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
162 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000163 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000164 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
165 &Count, OriginalPorts, OriginalBehaviors,
166 OriginalFlavors);
167 if (err == KERN_SUCCESS) {
168 // replace each with MACH_PORT_NULL.
169 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000170 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000171 MACH_PORT_NULL, OriginalBehaviors[i],
172 OriginalFlavors[i]);
173 }
174
175 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000176 signal(SIGABRT, _exit);
177 signal(SIGILL, _exit);
178 signal(SIGFPE, _exit);
179 signal(SIGSEGV, _exit);
180 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000181#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000182}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000183
Reid Spencer6f802ba2005-01-01 22:29:26 +0000184bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000185 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000186}
187
188bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000189 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000190}
191
192bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000193 return FileDescriptorIsDisplayed(STDERR_FILENO);
194}
195
196bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000197#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000198 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000199#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000200 // If we don't have isatty, just return false.
201 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000202#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000203}
Douglas Gregor15436612009-05-11 18:05:52 +0000204
205static unsigned getColumns(int FileID) {
206 // If COLUMNS is defined in the environment, wrap to that many columns.
207 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
208 int Columns = std::atoi(ColumnsStr);
209 if (Columns > 0)
210 return Columns;
211 }
212
213 unsigned Columns = 0;
214
Douglas Gregorb81294d2009-05-18 17:21:34 +0000215#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000216 // Try to determine the width of the terminal.
217 struct winsize ws;
218 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
219 Columns = ws.ws_col;
220#endif
221
222 return Columns;
223}
224
225unsigned Process::StandardOutColumns() {
226 if (!StandardOutIsDisplayed())
227 return 0;
228
229 return getColumns(1);
230}
231
232unsigned Process::StandardErrColumns() {
233 if (!StandardErrIsDisplayed())
234 return 0;
235
236 return getColumns(2);
237}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000238
Chandler Carruth91219852013-08-12 10:40:11 +0000239#ifdef HAVE_TERMINFO
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000240// We manually declare these extern functions because finding the correct
Chandler Carruth91219852013-08-12 10:40:11 +0000241// headers from various terminfo, curses, or other sources is harder than
242// writing their specs down.
243extern "C" int setupterm(char *term, int filedes, int *errret);
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000244extern "C" struct term *set_curterm(struct term *termp);
245extern "C" int del_curterm(struct term *termp);
Chandler Carruth91219852013-08-12 10:40:11 +0000246extern "C" int tigetnum(char *capname);
247#endif
248
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000249static bool terminalHasColors(int fd) {
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000250#ifdef HAVE_TERMINFO
251 // First, acquire a global lock because these C routines are thread hostile.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000252 static sys::Mutex M;
253 MutexGuard G(M);
254
255 int errret = 0;
Chandler Carruth91219852013-08-12 10:40:11 +0000256 if (setupterm((char *)0, fd, &errret) != 0)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000257 // Regardless of why, if we can't get terminfo, we shouldn't try to print
258 // colors.
259 return false;
260
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000261 // Test whether the terminal as set up supports color output. How to do this
262 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
263 // would be nice to avoid a dependency on curses proper when we can make do
264 // with a minimal terminfo parsing library. Also, we don't really care whether
265 // the terminal supports the curses-specific color changing routines, merely
266 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
267 // strategy here is just to query the baseline colors capability and if it
268 // supports colors at all to assume it will translate the escape codes into
269 // whatever range of colors it does support. We can add more detailed tests
270 // here if users report them as necessary.
271 //
272 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
273 // the terminfo says that no colors are supported.
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000274 bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
275
276 // Now extract the structure allocated by setupterm and free its memory
277 // through a really silly dance.
278 struct term *termp = set_curterm((struct term *)0);
279 (void)del_curterm(termp); // Drop any errors here.
280
281 // Return true if we found a color capabilities for the current terminal.
282 if (HasColors)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000283 return true;
284#endif
285
286 // Otherwise, be conservative.
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000287 return false;
288}
289
Daniel Dunbar712de822012-07-20 18:29:38 +0000290bool Process::FileDescriptorHasColors(int fd) {
291 // A file descriptor has colors if it is displayed and the terminal has
292 // colors.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000293 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
Daniel Dunbar712de822012-07-20 18:29:38 +0000294}
295
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000296bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000297 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000298}
299
300bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000301 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000302}
303
304bool Process::ColorNeedsFlush() {
305 // No, we use ANSI escape sequences.
306 return false;
307}
308
309#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
310
311#define ALLCOLORS(FGBG,BOLD) {\
312 COLOR(FGBG, "0", BOLD),\
313 COLOR(FGBG, "1", BOLD),\
314 COLOR(FGBG, "2", BOLD),\
315 COLOR(FGBG, "3", BOLD),\
316 COLOR(FGBG, "4", BOLD),\
317 COLOR(FGBG, "5", BOLD),\
318 COLOR(FGBG, "6", BOLD),\
319 COLOR(FGBG, "7", BOLD)\
320 }
321
Nuno Lopes129819d2009-12-23 17:48:10 +0000322static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000323 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
324 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
325};
326
327const char *Process::OutputColor(char code, bool bold, bool bg) {
328 return colorcodes[bg?1:0][bold?1:0][code&7];
329}
330
331const char *Process::OutputBold(bool bg) {
332 return "\033[1m";
333}
334
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000335const char *Process::OutputReverse() {
336 return "\033[7m";
337}
338
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000339const char *Process::ResetColor() {
340 return "\033[0m";
341}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000342
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000343#if !defined(HAVE_ARC4RANDOM)
344static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000345 // Attempt to get the initial seed from /dev/urandom, if possible.
346 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
347 unsigned seed;
348 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000349 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000350
351 // Return the seed if the read was successful.
352 if (count == 1)
353 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000354 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000355
356 // Otherwise, swizzle the current time and the process ID to form a reasonable
357 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000358 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000359 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000360}
361#endif
362
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000363unsigned llvm::sys::Process::GetRandomNumber() {
364#if defined(HAVE_ARC4RANDOM)
365 return arc4random();
366#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000367 static int x = (::srand(GetRandomNumberSeed()), 0);
368 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000369 return ::rand();
370#endif
371}