blob: 174112e8c2ab81abf8f48b1c6d83b7a948e04c51 [file] [log] [blame]
Reid Spencer27dafe12004-09-11 04:56:56 +00001//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
Michael J. Spencer1f6efa32010-11-29 18:16:10 +00002//
Reid Spencer27dafe12004-09-11 04:56:56 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-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. Spencer1f6efa32010-11-29 18:16:10 +00007//
Reid Spencer27dafe12004-09-11 04:56:56 +00008//===----------------------------------------------------------------------===//
9//
10// This file provides the generic Unix implementation of the Process class.
11//
12//===----------------------------------------------------------------------===//
13
Reid Spencer721d9aa2004-12-20 00:59:28 +000014#include "Unix.h"
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +000015#include "llvm/ADT/Hashing.h"
16#include "llvm/Support/TimeValue.h"
Reid Spencer721d9aa2004-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
Edward O'Callaghanbd5dc452009-11-02 03:20:57 +000023// DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead,
24// Unix.h includes this for us already.
25#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__)
Reid Spencer721d9aa2004-12-20 00:59:28 +000026#include <malloc.h>
27#endif
Chris Lattner513a9542005-11-14 07:00:29 +000028#ifdef HAVE_MALLOC_MALLOC_H
29#include <malloc/malloc.h>
30#endif
Douglas Gregor01746742009-05-11 18:05:52 +000031#ifdef HAVE_SYS_IOCTL_H
32# include <sys/ioctl.h>
33#endif
Douglas Gregor071d73d2009-05-18 17:21:34 +000034#ifdef HAVE_TERMIOS_H
35# include <termios.h>
36#endif
Reid Spencer27dafe12004-09-11 04:56:56 +000037
38//===----------------------------------------------------------------------===//
39//=== WARNING: Implementation here must contain only generic UNIX code that
40//=== is guaranteed to work on *all* UNIX variants.
41//===----------------------------------------------------------------------===//
42
Chris Lattner26b6c0b2006-09-14 06:01:41 +000043using namespace llvm;
Reid Spencer27dafe12004-09-11 04:56:56 +000044using namespace sys;
45
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000046unsigned
47Process::GetPageSize()
Reid Spencer721d9aa2004-12-20 00:59:28 +000048{
Jay Foada14be3b2009-05-23 17:57:59 +000049#if defined(__CYGWIN__)
50 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
51 // memory protection and mmap() is 4k.
52 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Anderson0d1ea252009-08-19 21:48:34 +000053 const int page_size = 0x1000;
Jay Foada14be3b2009-05-23 17:57:59 +000054#elif defined(HAVE_GETPAGESIZE)
Owen Anderson0d1ea252009-08-19 21:48:34 +000055 const int page_size = ::getpagesize();
Reid Spencer721d9aa2004-12-20 00:59:28 +000056#elif defined(HAVE_SYSCONF)
Owen Anderson0d1ea252009-08-19 21:48:34 +000057 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencer721d9aa2004-12-20 00:59:28 +000058#else
59#warning Cannot get the page size on this machine
60#endif
Reid Spencer27dafe12004-09-11 04:56:56 +000061 return static_cast<unsigned>(page_size);
62}
63
Chris Lattner513a9542005-11-14 07:00:29 +000064size_t Process::GetMallocUsage() {
Reid Spencerbc1ee842004-12-20 16:06:44 +000065#if defined(HAVE_MALLINFO)
Reid Spencer721d9aa2004-12-20 00:59:28 +000066 struct mallinfo mi;
67 mi = ::mallinfo();
68 return mi.uordblks;
Chris Lattnerc590e9a2005-11-14 07:27:56 +000069#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
70 malloc_statistics_t Stats;
71 malloc_zone_statistics(malloc_default_zone(), &Stats);
72 return Stats.size_in_use; // darwin
Reid Spencerbc1ee842004-12-20 16:06:44 +000073#elif defined(HAVE_SBRK)
Reid Spencer721d9aa2004-12-20 00:59:28 +000074 // Note this is only an approximation and more closely resembles
75 // the value returned by mallinfo in the arena field.
Chris Lattner513a9542005-11-14 07:00:29 +000076 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
77 char *EndOfMemory = (char*)sbrk(0);
78 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
79 return EndOfMemory - StartOfMemory;
Reid Spencer721d9aa2004-12-20 00:59:28 +000080 else
81 return 0;
82#else
83#warning Cannot get malloc info on this platform
84 return 0;
85#endif
86}
87
Jeff Cohene269a1a2005-01-08 20:15:57 +000088size_t
Reid Spencer721d9aa2004-12-20 00:59:28 +000089Process::GetTotalMemoryUsage()
90{
Reid Spencerbc1ee842004-12-20 16:06:44 +000091#if defined(HAVE_MALLINFO)
Reid Spencer721d9aa2004-12-20 00:59:28 +000092 struct mallinfo mi = ::mallinfo();
93 return mi.uordblks + mi.hblkhd;
Chris Lattnerc590e9a2005-11-14 07:27:56 +000094#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
95 malloc_statistics_t Stats;
96 malloc_zone_statistics(malloc_default_zone(), &Stats);
97 return Stats.size_allocated; // darwin
Edward O'Callaghandf406642009-10-12 04:57:20 +000098#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
Reid Spencered5e7bf2004-12-20 16:33:37 +000099 struct rusage usage;
100 ::getrusage(RUSAGE_SELF, &usage);
101 return usage.ru_maxrss;
Reid Spencer721d9aa2004-12-20 00:59:28 +0000102#else
103#warning Cannot get total memory size on this platform
104 return 0;
105#endif
106}
107
108void
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000109Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
Reid Spencer721d9aa2004-12-20 00:59:28 +0000110 TimeValue& sys_time)
111{
112 elapsed = TimeValue::now();
Chris Lattner095cc372006-05-12 18:20:39 +0000113#if defined(HAVE_GETRUSAGE)
Reid Spencer721d9aa2004-12-20 00:59:28 +0000114 struct rusage usage;
115 ::getrusage(RUSAGE_SELF, &usage);
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000116 user_time = TimeValue(
117 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
118 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
Reid Spencer8b662892004-12-20 21:43:33 +0000119 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000120 sys_time = TimeValue(
121 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
122 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
Reid Spencer8b662892004-12-20 21:43:33 +0000123 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Reid Spencer721d9aa2004-12-20 00:59:28 +0000124#else
125#warning Cannot get usage times on this platform
126 user_time.seconds(0);
127 user_time.microseconds(0);
128 sys_time.seconds(0);
129 sys_time.microseconds(0);
130#endif
131}
132
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000133int Process::GetCurrentUserId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000134 return getuid();
135}
136
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000137int Process::GetCurrentGroupId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000138 return getgid();
139}
140
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000141#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begemane9563982008-04-12 00:47:46 +0000142#include <mach/mach.h>
143#endif
144
Reid Spencer68fdcc12004-12-27 06:17:27 +0000145// 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.
148void Process::PreventCoreFiles() {
149#if HAVE_SETRLIMIT
150 struct rlimit rlim;
151 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattner505f9c82006-05-14 18:53:09 +0000152 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencer68fdcc12004-12-27 06:17:27 +0000153#endif
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000154
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000155#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begemane9563982008-04-12 00:47:46 +0000156 // Disable crash reporting on Mac OS X 10.0-10.4
157
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];
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000164 kern_return_t err =
Nate Begemane9563982008-04-12 00:47:46 +0000165 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
166 &Count, OriginalPorts, OriginalBehaviors,
167 OriginalFlavors);
168 if (err == KERN_SUCCESS) {
169 // replace each with MACH_PORT_NULL.
170 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000171 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begemane9563982008-04-12 00:47:46 +0000172 MACH_PORT_NULL, OriginalBehaviors[i],
173 OriginalFlavors[i]);
174 }
175
176 // Disable crash reporting on Mac OS X 10.5
Nate Begeman82b53cd2008-03-31 22:19:25 +0000177 signal(SIGABRT, _exit);
178 signal(SIGILL, _exit);
179 signal(SIGFPE, _exit);
180 signal(SIGSEGV, _exit);
181 signal(SIGBUS, _exit);
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000182#endif
Reid Spencer68fdcc12004-12-27 06:17:27 +0000183}
Reid Spencer721d9aa2004-12-20 00:59:28 +0000184
Reid Spencera01aade2005-01-01 22:29:26 +0000185bool Process::StandardInIsUserInput() {
Dan Gohmanec080462009-09-11 20:46:33 +0000186 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000187}
188
189bool Process::StandardOutIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000190 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000191}
192
193bool Process::StandardErrIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000194 return FileDescriptorIsDisplayed(STDERR_FILENO);
195}
196
197bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencera01aade2005-01-01 22:29:26 +0000198#if HAVE_ISATTY
Dan Gohmanec080462009-09-11 20:46:33 +0000199 return isatty(fd);
Duncan Sands740eb532009-09-06 10:53:22 +0000200#else
Reid Spencera01aade2005-01-01 22:29:26 +0000201 // If we don't have isatty, just return false.
202 return false;
Duncan Sands740eb532009-09-06 10:53:22 +0000203#endif
Reid Spencera01aade2005-01-01 22:29:26 +0000204}
Douglas Gregor01746742009-05-11 18:05:52 +0000205
206static unsigned getColumns(int FileID) {
207 // If COLUMNS is defined in the environment, wrap to that many columns.
208 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
209 int Columns = std::atoi(ColumnsStr);
210 if (Columns > 0)
211 return Columns;
212 }
213
214 unsigned Columns = 0;
215
Douglas Gregor071d73d2009-05-18 17:21:34 +0000216#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor01746742009-05-11 18:05:52 +0000217 // Try to determine the width of the terminal.
218 struct winsize ws;
219 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
220 Columns = ws.ws_col;
221#endif
222
223 return Columns;
224}
225
226unsigned Process::StandardOutColumns() {
227 if (!StandardOutIsDisplayed())
228 return 0;
229
230 return getColumns(1);
231}
232
233unsigned Process::StandardErrColumns() {
234 if (!StandardErrIsDisplayed())
235 return 0;
236
237 return getColumns(2);
238}
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000239
240static bool terminalHasColors() {
241 if (const char *term = std::getenv("TERM")) {
242 // Most modern terminals support ANSI escape sequences for colors.
243 // We could check terminfo, or have a list of known terms that support
244 // colors, but that would be overkill.
245 // The user can always ask for no colors by setting TERM to dumb, or
246 // using a commandline flag.
247 return strcmp(term, "dumb") != 0;
248 }
249 return false;
250}
251
Daniel Dunbar7d836582012-07-20 18:29:38 +0000252bool Process::FileDescriptorHasColors(int fd) {
253 // A file descriptor has colors if it is displayed and the terminal has
254 // colors.
255 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
256}
257
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000258bool Process::StandardOutHasColors() {
Daniel Dunbar7d836582012-07-20 18:29:38 +0000259 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000260}
261
262bool Process::StandardErrHasColors() {
Daniel Dunbar7d836582012-07-20 18:29:38 +0000263 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000264}
265
266bool Process::ColorNeedsFlush() {
267 // No, we use ANSI escape sequences.
268 return false;
269}
270
271#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
272
273#define ALLCOLORS(FGBG,BOLD) {\
274 COLOR(FGBG, "0", BOLD),\
275 COLOR(FGBG, "1", BOLD),\
276 COLOR(FGBG, "2", BOLD),\
277 COLOR(FGBG, "3", BOLD),\
278 COLOR(FGBG, "4", BOLD),\
279 COLOR(FGBG, "5", BOLD),\
280 COLOR(FGBG, "6", BOLD),\
281 COLOR(FGBG, "7", BOLD)\
282 }
283
Nuno Lopesec9d8b02009-12-23 17:48:10 +0000284static const char colorcodes[2][2][8][10] = {
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000285 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
286 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
287};
288
289const char *Process::OutputColor(char code, bool bold, bool bg) {
290 return colorcodes[bg?1:0][bold?1:0][code&7];
291}
292
293const char *Process::OutputBold(bool bg) {
294 return "\033[1m";
295}
296
Benjamin Kramer246de852012-04-16 08:56:50 +0000297const char *Process::OutputReverse() {
298 return "\033[7m";
299}
300
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000301const char *Process::ResetColor() {
302 return "\033[0m";
303}
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000304
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000305#if !defined(HAVE_ARC4RANDOM)
306static unsigned GetRandomNumberSeed() {
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000307 // Attempt to get the initial seed from /dev/urandom, if possible.
308 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
309 unsigned seed;
310 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000311 ::fclose(RandomSource);
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000312
313 // Return the seed if the read was successful.
314 if (count == 1)
315 return seed;
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000316 }
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000317
318 // Otherwise, swizzle the current time and the process ID to form a reasonable
319 // seed.
320 TimeValue Now = llvm::TimeValue::now();
321 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000322}
323#endif
324
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000325unsigned llvm::sys::Process::GetRandomNumber() {
326#if defined(HAVE_ARC4RANDOM)
327 return arc4random();
328#else
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000329 static int x = (::srand(GetRandomNumberSeed()), 0);
330 (void)x;
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000331 return ::rand();
332#endif
333}