blob: 5204147ce316993a4ea86521615f70d0dffdeaa8 [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
Michael J. Spencer447762d2010-11-29 18:16:10 +000047unsigned
48Process::GetPageSize()
Reid Spencerac38f3a2004-12-20 00:59:28 +000049{
Jay Foadc1fca9fb2009-05-23 17:57:59 +000050#if defined(__CYGWIN__)
51 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
52 // memory protection and mmap() is 4k.
53 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Andersona83e8682009-08-19 21:48:34 +000054 const int page_size = 0x1000;
Jay Foadc1fca9fb2009-05-23 17:57:59 +000055#elif defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000056 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000057#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +000058 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +000059#else
60#warning Cannot get the page size on this machine
61#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000062 return static_cast<unsigned>(page_size);
63}
64
Chris Lattner698fa762005-11-14 07:00:29 +000065size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +000066#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +000067 struct mallinfo mi;
68 mi = ::mallinfo();
69 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +000070#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
71 malloc_statistics_t Stats;
72 malloc_zone_statistics(malloc_default_zone(), &Stats);
73 return Stats.size_in_use; // darwin
Reid Spencer1cf74ce2004-12-20 16:06:44 +000074#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +000075 // Note this is only an approximation and more closely resembles
76 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +000077 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
78 char *EndOfMemory = (char*)sbrk(0);
79 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
80 return EndOfMemory - StartOfMemory;
Reid Spencerac38f3a2004-12-20 00:59:28 +000081 else
82 return 0;
83#else
84#warning Cannot get malloc info on this platform
85 return 0;
86#endif
87}
88
Jeff Cohen1a26d152005-01-08 20:15:57 +000089size_t
Reid Spencerac38f3a2004-12-20 00:59:28 +000090Process::GetTotalMemoryUsage()
91{
Reid Spencer1cf74ce2004-12-20 16:06:44 +000092#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +000093 struct mallinfo mi = ::mallinfo();
94 return mi.uordblks + mi.hblkhd;
Chris Lattner16cbc6a2005-11-14 07:27:56 +000095#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
96 malloc_statistics_t Stats;
97 malloc_zone_statistics(malloc_default_zone(), &Stats);
98 return Stats.size_allocated; // darwin
Edward O'Callaghan8227b052009-10-12 04:57:20 +000099#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
Reid Spencer8005e662004-12-20 16:33:37 +0000100 struct rusage usage;
101 ::getrusage(RUSAGE_SELF, &usage);
102 return usage.ru_maxrss;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000103#else
104#warning Cannot get total memory size on this platform
105 return 0;
106#endif
107}
108
109void
Michael J. Spencer447762d2010-11-29 18:16:10 +0000110Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
Reid Spencerac38f3a2004-12-20 00:59:28 +0000111 TimeValue& sys_time)
112{
113 elapsed = TimeValue::now();
Chris Lattner227d4422006-05-12 18:20:39 +0000114#if defined(HAVE_GETRUSAGE)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000115 struct rusage usage;
116 ::getrusage(RUSAGE_SELF, &usage);
Michael J. Spencer447762d2010-11-29 18:16:10 +0000117 user_time = TimeValue(
118 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
119 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
Reid Spencerd4c69882004-12-20 21:43:33 +0000120 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Michael J. Spencer447762d2010-11-29 18:16:10 +0000121 sys_time = TimeValue(
122 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
123 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
Reid Spencerd4c69882004-12-20 21:43:33 +0000124 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Reid Spencerac38f3a2004-12-20 00:59:28 +0000125#else
126#warning Cannot get usage times on this platform
127 user_time.seconds(0);
128 user_time.microseconds(0);
129 sys_time.seconds(0);
130 sys_time.microseconds(0);
131#endif
132}
133
Chris Lattner2f107cf2006-09-14 06:01:41 +0000134int Process::GetCurrentUserId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000135 return getuid();
136}
137
Chris Lattner2f107cf2006-09-14 06:01:41 +0000138int Process::GetCurrentGroupId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000139 return getgid();
140}
141
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000142#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000143#include <mach/mach.h>
144#endif
145
Reid Spencercf15b872004-12-27 06:17:27 +0000146// Some LLVM programs such as bugpoint produce core files as a normal part of
147// their operation. To prevent the disk from filling up, this function
148// does what's necessary to prevent their generation.
149void Process::PreventCoreFiles() {
150#if HAVE_SETRLIMIT
151 struct rlimit rlim;
152 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000153 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000154#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000155
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000156#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000157 // Disable crash reporting on Mac OS X 10.0-10.4
158
159 // get information about the original set of exception ports for the task
160 mach_msg_type_number_t Count = 0;
161 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
162 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
163 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
164 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000165 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000166 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
167 &Count, OriginalPorts, OriginalBehaviors,
168 OriginalFlavors);
169 if (err == KERN_SUCCESS) {
170 // replace each with MACH_PORT_NULL.
171 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000172 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000173 MACH_PORT_NULL, OriginalBehaviors[i],
174 OriginalFlavors[i]);
175 }
176
177 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000178 signal(SIGABRT, _exit);
179 signal(SIGILL, _exit);
180 signal(SIGFPE, _exit);
181 signal(SIGSEGV, _exit);
182 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000183#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000184}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000185
Reid Spencer6f802ba2005-01-01 22:29:26 +0000186bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000187 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000188}
189
190bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000191 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000192}
193
194bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000195 return FileDescriptorIsDisplayed(STDERR_FILENO);
196}
197
198bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000199#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000200 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000201#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000202 // If we don't have isatty, just return false.
203 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000204#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000205}
Douglas Gregor15436612009-05-11 18:05:52 +0000206
207static unsigned getColumns(int FileID) {
208 // If COLUMNS is defined in the environment, wrap to that many columns.
209 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
210 int Columns = std::atoi(ColumnsStr);
211 if (Columns > 0)
212 return Columns;
213 }
214
215 unsigned Columns = 0;
216
Douglas Gregorb81294d2009-05-18 17:21:34 +0000217#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000218 // Try to determine the width of the terminal.
219 struct winsize ws;
220 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
221 Columns = ws.ws_col;
222#endif
223
224 return Columns;
225}
226
227unsigned Process::StandardOutColumns() {
228 if (!StandardOutIsDisplayed())
229 return 0;
230
231 return getColumns(1);
232}
233
234unsigned Process::StandardErrColumns() {
235 if (!StandardErrIsDisplayed())
236 return 0;
237
238 return getColumns(2);
239}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000240
241static bool terminalHasColors() {
242 if (const char *term = std::getenv("TERM")) {
243 // Most modern terminals support ANSI escape sequences for colors.
244 // We could check terminfo, or have a list of known terms that support
245 // colors, but that would be overkill.
246 // The user can always ask for no colors by setting TERM to dumb, or
247 // using a commandline flag.
248 return strcmp(term, "dumb") != 0;
249 }
250 return false;
251}
252
Daniel Dunbar712de822012-07-20 18:29:38 +0000253bool Process::FileDescriptorHasColors(int fd) {
254 // A file descriptor has colors if it is displayed and the terminal has
255 // colors.
256 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
257}
258
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000259bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000260 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000261}
262
263bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000264 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000265}
266
267bool Process::ColorNeedsFlush() {
268 // No, we use ANSI escape sequences.
269 return false;
270}
271
272#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
273
274#define ALLCOLORS(FGBG,BOLD) {\
275 COLOR(FGBG, "0", BOLD),\
276 COLOR(FGBG, "1", BOLD),\
277 COLOR(FGBG, "2", BOLD),\
278 COLOR(FGBG, "3", BOLD),\
279 COLOR(FGBG, "4", BOLD),\
280 COLOR(FGBG, "5", BOLD),\
281 COLOR(FGBG, "6", BOLD),\
282 COLOR(FGBG, "7", BOLD)\
283 }
284
Nuno Lopes129819d2009-12-23 17:48:10 +0000285static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000286 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
287 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
288};
289
290const char *Process::OutputColor(char code, bool bold, bool bg) {
291 return colorcodes[bg?1:0][bold?1:0][code&7];
292}
293
294const char *Process::OutputBold(bool bg) {
295 return "\033[1m";
296}
297
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000298const char *Process::OutputReverse() {
299 return "\033[7m";
300}
301
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000302const char *Process::ResetColor() {
303 return "\033[0m";
304}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000305
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000306#if !defined(HAVE_ARC4RANDOM)
307static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000308 // Attempt to get the initial seed from /dev/urandom, if possible.
309 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
310 unsigned seed;
311 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000312 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000313
314 // Return the seed if the read was successful.
315 if (count == 1)
316 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000317 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000318
319 // Otherwise, swizzle the current time and the process ID to form a reasonable
320 // seed.
321 TimeValue Now = llvm::TimeValue::now();
322 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000323}
324#endif
325
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000326unsigned llvm::sys::Process::GetRandomNumber() {
327#if defined(HAVE_ARC4RANDOM)
328 return arc4random();
329#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000330 static int x = (::srand(GetRandomNumberSeed()), 0);
331 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000332 return ::rand();
333#endif
334}