blob: 538f05f980d476f8c206d574080d5e7179d2bab3 [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
Chandler Carruth15dcad92012-12-31 23:23:35 +000091static unsigned getPageSize() {
Jay Foadc1fca9fb2009-05-23 17:57:59 +000092#if defined(__CYGWIN__)
93 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
94 // memory protection and mmap() is 4k.
95 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Andersona83e8682009-08-19 21:48:34 +000096 const int page_size = 0x1000;
Jay Foadc1fca9fb2009-05-23 17:57:59 +000097#elif defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000098 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000099#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +0000100 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +0000101#else
102#warning Cannot get the page size on this machine
103#endif
Reid Spencer33b9d772004-09-11 04:56:56 +0000104 return static_cast<unsigned>(page_size);
105}
106
Chandler Carruth15dcad92012-12-31 23:23:35 +0000107// This constructor guaranteed to be run exactly once on a single thread, and
108// sets up various process invariants that can be queried cheaply from then on.
109self_process::self_process() : PageSize(getPageSize()) {
110}
111
112
Chris Lattner698fa762005-11-14 07:00:29 +0000113size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000114#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000115 struct mallinfo mi;
116 mi = ::mallinfo();
117 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000118#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
119 malloc_statistics_t Stats;
120 malloc_zone_statistics(malloc_default_zone(), &Stats);
121 return Stats.size_in_use; // darwin
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000122#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000123 // Note this is only an approximation and more closely resembles
124 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +0000125 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
126 char *EndOfMemory = (char*)sbrk(0);
127 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
128 return EndOfMemory - StartOfMemory;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000129 else
130 return 0;
131#else
132#warning Cannot get malloc info on this platform
133 return 0;
134#endif
135}
136
Chandler Carruthef7f9682013-01-04 23:19:55 +0000137void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
138 TimeValue &sys_time) {
Reid Spencerac38f3a2004-12-20 00:59:28 +0000139 elapsed = TimeValue::now();
Chandler Carruthef7f9682013-01-04 23:19:55 +0000140 llvm::tie(user_time, sys_time) = getRUsageTimes();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000141}
142
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000143#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000144#include <mach/mach.h>
145#endif
146
Reid Spencercf15b872004-12-27 06:17:27 +0000147// Some LLVM programs such as bugpoint produce core files as a normal part of
148// their operation. To prevent the disk from filling up, this function
149// does what's necessary to prevent their generation.
150void Process::PreventCoreFiles() {
151#if HAVE_SETRLIMIT
152 struct rlimit rlim;
153 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000154 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000155#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000156
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000157#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000158 // Disable crash reporting on Mac OS X 10.0-10.4
159
160 // get information about the original set of exception ports for the task
161 mach_msg_type_number_t Count = 0;
162 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
163 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
164 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
165 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000166 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000167 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
168 &Count, OriginalPorts, OriginalBehaviors,
169 OriginalFlavors);
170 if (err == KERN_SUCCESS) {
171 // replace each with MACH_PORT_NULL.
172 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000173 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000174 MACH_PORT_NULL, OriginalBehaviors[i],
175 OriginalFlavors[i]);
176 }
177
178 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000179 signal(SIGABRT, _exit);
180 signal(SIGILL, _exit);
181 signal(SIGFPE, _exit);
182 signal(SIGSEGV, _exit);
183 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000184#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000185}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000186
Reid Spencer6f802ba2005-01-01 22:29:26 +0000187bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000188 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000189}
190
191bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000192 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000193}
194
195bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000196 return FileDescriptorIsDisplayed(STDERR_FILENO);
197}
198
199bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000200#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000201 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000202#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000203 // If we don't have isatty, just return false.
204 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000205#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000206}
Douglas Gregor15436612009-05-11 18:05:52 +0000207
208static unsigned getColumns(int FileID) {
209 // If COLUMNS is defined in the environment, wrap to that many columns.
210 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
211 int Columns = std::atoi(ColumnsStr);
212 if (Columns > 0)
213 return Columns;
214 }
215
216 unsigned Columns = 0;
217
Douglas Gregorb81294d2009-05-18 17:21:34 +0000218#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000219 // Try to determine the width of the terminal.
220 struct winsize ws;
221 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
222 Columns = ws.ws_col;
223#endif
224
225 return Columns;
226}
227
228unsigned Process::StandardOutColumns() {
229 if (!StandardOutIsDisplayed())
230 return 0;
231
232 return getColumns(1);
233}
234
235unsigned Process::StandardErrColumns() {
236 if (!StandardErrIsDisplayed())
237 return 0;
238
239 return getColumns(2);
240}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000241
Chandler Carruth91219852013-08-12 10:40:11 +0000242#ifdef HAVE_TERMINFO
243// We manually declare these two extern functions because finding the correct
244// headers from various terminfo, curses, or other sources is harder than
245// writing their specs down.
246extern "C" int setupterm(char *term, int filedes, int *errret);
247extern "C" int tigetnum(char *capname);
248#endif
249
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000250static bool terminalHasColors(int fd) {
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000251#ifdef HAVE_TERMINFO
252 // First, acquire a global lock because these C routines are thread hostile.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000253 static sys::Mutex M;
254 MutexGuard G(M);
255
256 int errret = 0;
Chandler Carruth91219852013-08-12 10:40:11 +0000257 if (setupterm((char *)0, fd, &errret) != 0)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000258 // Regardless of why, if we can't get terminfo, we shouldn't try to print
259 // colors.
260 return false;
261
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000262 // Test whether the terminal as set up supports color output. How to do this
263 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
264 // would be nice to avoid a dependency on curses proper when we can make do
265 // with a minimal terminfo parsing library. Also, we don't really care whether
266 // the terminal supports the curses-specific color changing routines, merely
267 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
268 // strategy here is just to query the baseline colors capability and if it
269 // supports colors at all to assume it will translate the escape codes into
270 // whatever range of colors it does support. We can add more detailed tests
271 // here if users report them as necessary.
272 //
273 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
274 // the terminfo says that no colors are supported.
Benjamin Kramer5bd3fab2013-08-13 09:57:55 +0000275 if (tigetnum(const_cast<char *>("colors")) > 0)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000276 return true;
277#endif
278
279 // Otherwise, be conservative.
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000280 return false;
281}
282
Daniel Dunbar712de822012-07-20 18:29:38 +0000283bool Process::FileDescriptorHasColors(int fd) {
284 // A file descriptor has colors if it is displayed and the terminal has
285 // colors.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000286 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
Daniel Dunbar712de822012-07-20 18:29:38 +0000287}
288
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000289bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000290 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000291}
292
293bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000294 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000295}
296
297bool Process::ColorNeedsFlush() {
298 // No, we use ANSI escape sequences.
299 return false;
300}
301
302#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
303
304#define ALLCOLORS(FGBG,BOLD) {\
305 COLOR(FGBG, "0", BOLD),\
306 COLOR(FGBG, "1", BOLD),\
307 COLOR(FGBG, "2", BOLD),\
308 COLOR(FGBG, "3", BOLD),\
309 COLOR(FGBG, "4", BOLD),\
310 COLOR(FGBG, "5", BOLD),\
311 COLOR(FGBG, "6", BOLD),\
312 COLOR(FGBG, "7", BOLD)\
313 }
314
Nuno Lopes129819d2009-12-23 17:48:10 +0000315static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000316 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
317 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
318};
319
320const char *Process::OutputColor(char code, bool bold, bool bg) {
321 return colorcodes[bg?1:0][bold?1:0][code&7];
322}
323
324const char *Process::OutputBold(bool bg) {
325 return "\033[1m";
326}
327
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000328const char *Process::OutputReverse() {
329 return "\033[7m";
330}
331
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000332const char *Process::ResetColor() {
333 return "\033[0m";
334}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000335
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000336#if !defined(HAVE_ARC4RANDOM)
337static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000338 // Attempt to get the initial seed from /dev/urandom, if possible.
339 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
340 unsigned seed;
341 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000342 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000343
344 // Return the seed if the read was successful.
345 if (count == 1)
346 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000347 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000348
349 // Otherwise, swizzle the current time and the process ID to form a reasonable
350 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000351 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000352 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000353}
354#endif
355
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000356unsigned llvm::sys::Process::GetRandomNumber() {
357#if defined(HAVE_ARC4RANDOM)
358 return arc4random();
359#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000360 static int x = (::srand(GetRandomNumberSeed()), 0);
361 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000362 return ::rand();
363#endif
364}