blob: 9a4454f1c650e01a73f6c7fceacc9cf7f774ed7e [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"
16#include "llvm/Support/TimeValue.h"
Reid Spencerac38f3a2004-12-20 00:59:28 +000017#ifdef HAVE_SYS_TIME_H
18#include <sys/time.h>
19#endif
20#ifdef HAVE_SYS_RESOURCE_H
21#include <sys/resource.h>
22#endif
Eric Christopher22738d02012-08-06 20:52:18 +000023// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
24// <stdlib.h> instead. Unix.h includes this for us already.
25#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
26 !defined(__OpenBSD__) && !defined(__Bitrig__)
Reid Spencerac38f3a2004-12-20 00:59:28 +000027#include <malloc.h>
28#endif
Chris Lattner698fa762005-11-14 07:00:29 +000029#ifdef HAVE_MALLOC_MALLOC_H
30#include <malloc/malloc.h>
31#endif
Douglas Gregor15436612009-05-11 18:05:52 +000032#ifdef HAVE_SYS_IOCTL_H
33# include <sys/ioctl.h>
34#endif
Douglas Gregorb81294d2009-05-18 17:21:34 +000035#ifdef HAVE_TERMIOS_H
36# include <termios.h>
37#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000038
39//===----------------------------------------------------------------------===//
40//=== WARNING: Implementation here must contain only generic UNIX code that
41//=== is guaranteed to work on *all* UNIX variants.
42//===----------------------------------------------------------------------===//
43
Chris Lattner2f107cf2006-09-14 06:01:41 +000044using namespace llvm;
Reid Spencer33b9d772004-09-11 04:56:56 +000045using namespace sys;
46
Chandler Carruth97683aa2012-12-31 11:17:50 +000047
48process::id_type self_process::get_id() {
49 return getpid();
50}
51
Chandler Carruthef7f9682013-01-04 23:19:55 +000052static std::pair<TimeValue, TimeValue> getRUsageTimes() {
53#if defined(HAVE_GETRUSAGE)
54 struct rusage RU;
55 ::getrusage(RUSAGE_SELF, &RU);
56 return std::make_pair(
57 TimeValue(
58 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
59 static_cast<TimeValue::NanoSecondsType>(
60 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
61 TimeValue(
62 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
63 static_cast<TimeValue::NanoSecondsType>(
64 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
65#else
66#warning Cannot get usage times on this platform
67 return std::make_pair(TimeValue(), TimeValue());
68#endif
69}
70
71TimeValue self_process::get_user_time() const {
Chandler Carruthb5429f42013-01-05 00:42:50 +000072#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
Chandler Carruthef7f9682013-01-04 23:19:55 +000073 // Try to get a high resolution CPU timer.
74 struct timespec TS;
75 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
76 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
77 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
78#endif
79
80 // Otherwise fall back to rusage based timing.
81 return getRUsageTimes().first;
82}
83
84TimeValue self_process::get_system_time() const {
85 // We can only collect system time by inspecting the results of getrusage.
86 return getRUsageTimes().second;
87}
88
Chandler Carruth15dcad92012-12-31 23:23:35 +000089static unsigned getPageSize() {
Jay Foadc1fca9fb2009-05-23 17:57:59 +000090#if defined(__CYGWIN__)
91 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
92 // memory protection and mmap() is 4k.
93 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Andersona83e8682009-08-19 21:48:34 +000094 const int page_size = 0x1000;
Jay Foadc1fca9fb2009-05-23 17:57:59 +000095#elif defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000096 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000097#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +000098 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +000099#else
100#warning Cannot get the page size on this machine
101#endif
Reid Spencer33b9d772004-09-11 04:56:56 +0000102 return static_cast<unsigned>(page_size);
103}
104
Chandler Carruth15dcad92012-12-31 23:23:35 +0000105// 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.
107self_process::self_process() : PageSize(getPageSize()) {
108}
109
110
Chris Lattner698fa762005-11-14 07:00:29 +0000111size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000112#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000113 struct mallinfo mi;
114 mi = ::mallinfo();
115 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000116#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
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000120#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000121 // Note this is only an approximation and more closely resembles
122 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +0000123 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;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000127 else
128 return 0;
129#else
130#warning Cannot get malloc info on this platform
131 return 0;
132#endif
133}
134
Chandler Carruthef7f9682013-01-04 23:19:55 +0000135void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
136 TimeValue &sys_time) {
Reid Spencerac38f3a2004-12-20 00:59:28 +0000137 elapsed = TimeValue::now();
Chandler Carruthef7f9682013-01-04 23:19:55 +0000138 llvm::tie(user_time, sys_time) = getRUsageTimes();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000139}
140
Chris Lattner2f107cf2006-09-14 06:01:41 +0000141int Process::GetCurrentUserId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000142 return getuid();
143}
144
Chris Lattner2f107cf2006-09-14 06:01:41 +0000145int Process::GetCurrentGroupId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000146 return getgid();
147}
148
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000149#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000150#include <mach/mach.h>
151#endif
152
Reid Spencercf15b872004-12-27 06:17:27 +0000153// Some LLVM programs such as bugpoint produce core files as a normal part of
154// their operation. To prevent the disk from filling up, this function
155// does what's necessary to prevent their generation.
156void Process::PreventCoreFiles() {
157#if HAVE_SETRLIMIT
158 struct rlimit rlim;
159 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000160 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000161#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000162
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000163#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000164 // Disable crash reporting on Mac OS X 10.0-10.4
165
166 // get information about the original set of exception ports for the task
167 mach_msg_type_number_t Count = 0;
168 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
169 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
170 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
171 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000172 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000173 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
174 &Count, OriginalPorts, OriginalBehaviors,
175 OriginalFlavors);
176 if (err == KERN_SUCCESS) {
177 // replace each with MACH_PORT_NULL.
178 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000179 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000180 MACH_PORT_NULL, OriginalBehaviors[i],
181 OriginalFlavors[i]);
182 }
183
184 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000185 signal(SIGABRT, _exit);
186 signal(SIGILL, _exit);
187 signal(SIGFPE, _exit);
188 signal(SIGSEGV, _exit);
189 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000190#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000191}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000192
Reid Spencer6f802ba2005-01-01 22:29:26 +0000193bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000194 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000195}
196
197bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000198 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000199}
200
201bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000202 return FileDescriptorIsDisplayed(STDERR_FILENO);
203}
204
205bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000206#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000207 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000208#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000209 // If we don't have isatty, just return false.
210 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000211#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000212}
Douglas Gregor15436612009-05-11 18:05:52 +0000213
214static 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);
218 if (Columns > 0)
219 return Columns;
220 }
221
222 unsigned Columns = 0;
223
Douglas Gregorb81294d2009-05-18 17:21:34 +0000224#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000225 // Try to determine the width of the terminal.
226 struct winsize ws;
Evgeniy Stepanova5b58f92013-02-14 12:18:32 +0000227 // Zero-fill ws to avoid a false positive from MemorySanitizer.
228 memset(&ws, 0, sizeof(ws));
Douglas Gregor15436612009-05-11 18:05:52 +0000229 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
230 Columns = ws.ws_col;
231#endif
232
233 return Columns;
234}
235
236unsigned Process::StandardOutColumns() {
237 if (!StandardOutIsDisplayed())
238 return 0;
239
240 return getColumns(1);
241}
242
243unsigned Process::StandardErrColumns() {
244 if (!StandardErrIsDisplayed())
245 return 0;
246
247 return getColumns(2);
248}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000249
250static bool terminalHasColors() {
251 if (const char *term = std::getenv("TERM")) {
252 // Most modern terminals support ANSI escape sequences for colors.
253 // We could check terminfo, or have a list of known terms that support
254 // colors, but that would be overkill.
255 // The user can always ask for no colors by setting TERM to dumb, or
256 // using a commandline flag.
257 return strcmp(term, "dumb") != 0;
258 }
259 return false;
260}
261
Daniel Dunbar712de822012-07-20 18:29:38 +0000262bool Process::FileDescriptorHasColors(int fd) {
263 // A file descriptor has colors if it is displayed and the terminal has
264 // colors.
265 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
266}
267
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000268bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000269 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000270}
271
272bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000273 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000274}
275
276bool Process::ColorNeedsFlush() {
277 // No, we use ANSI escape sequences.
278 return false;
279}
280
281#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
282
283#define ALLCOLORS(FGBG,BOLD) {\
284 COLOR(FGBG, "0", BOLD),\
285 COLOR(FGBG, "1", BOLD),\
286 COLOR(FGBG, "2", BOLD),\
287 COLOR(FGBG, "3", BOLD),\
288 COLOR(FGBG, "4", BOLD),\
289 COLOR(FGBG, "5", BOLD),\
290 COLOR(FGBG, "6", BOLD),\
291 COLOR(FGBG, "7", BOLD)\
292 }
293
Nuno Lopes129819d2009-12-23 17:48:10 +0000294static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000295 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
296 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
297};
298
299const char *Process::OutputColor(char code, bool bold, bool bg) {
300 return colorcodes[bg?1:0][bold?1:0][code&7];
301}
302
303const char *Process::OutputBold(bool bg) {
304 return "\033[1m";
305}
306
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000307const char *Process::OutputReverse() {
308 return "\033[7m";
309}
310
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000311const char *Process::ResetColor() {
312 return "\033[0m";
313}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000314
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000315#if !defined(HAVE_ARC4RANDOM)
316static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000317 // Attempt to get the initial seed from /dev/urandom, if possible.
318 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
319 unsigned seed;
320 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000321 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000322
323 // Return the seed if the read was successful.
324 if (count == 1)
325 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000326 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000327
328 // Otherwise, swizzle the current time and the process ID to form a reasonable
329 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000330 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000331 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000332}
333#endif
334
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000335unsigned llvm::sys::Process::GetRandomNumber() {
336#if defined(HAVE_ARC4RANDOM)
337 return arc4random();
338#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000339 static int x = (::srand(GetRandomNumberSeed()), 0);
340 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000341 return ::rand();
342#endif
343}