blob: e96d37ce563fd941cd451b4dde3149bce16a094c [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
Eric Christopherb0f67592012-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 Spencer721d9aa2004-12-20 00:59:28 +000027#include <malloc.h>
28#endif
Chris Lattner513a9542005-11-14 07:00:29 +000029#ifdef HAVE_MALLOC_MALLOC_H
30#include <malloc/malloc.h>
31#endif
Douglas Gregor01746742009-05-11 18:05:52 +000032#ifdef HAVE_SYS_IOCTL_H
33# include <sys/ioctl.h>
34#endif
Douglas Gregor071d73d2009-05-18 17:21:34 +000035#ifdef HAVE_TERMIOS_H
36# include <termios.h>
37#endif
Reid Spencer27dafe12004-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 Lattner26b6c0b2006-09-14 06:01:41 +000044using namespace llvm;
Reid Spencer27dafe12004-09-11 04:56:56 +000045using namespace sys;
46
Chandler Carruth0184a842012-12-31 11:17:50 +000047
48process::id_type self_process::get_id() {
49 return getpid();
50}
51
52
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000053unsigned
54Process::GetPageSize()
Reid Spencer721d9aa2004-12-20 00:59:28 +000055{
Jay Foada14be3b2009-05-23 17:57:59 +000056#if defined(__CYGWIN__)
57 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
58 // memory protection and mmap() is 4k.
59 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Anderson0d1ea252009-08-19 21:48:34 +000060 const int page_size = 0x1000;
Jay Foada14be3b2009-05-23 17:57:59 +000061#elif defined(HAVE_GETPAGESIZE)
Owen Anderson0d1ea252009-08-19 21:48:34 +000062 const int page_size = ::getpagesize();
Reid Spencer721d9aa2004-12-20 00:59:28 +000063#elif defined(HAVE_SYSCONF)
Owen Anderson0d1ea252009-08-19 21:48:34 +000064 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencer721d9aa2004-12-20 00:59:28 +000065#else
66#warning Cannot get the page size on this machine
67#endif
Reid Spencer27dafe12004-09-11 04:56:56 +000068 return static_cast<unsigned>(page_size);
69}
70
Chris Lattner513a9542005-11-14 07:00:29 +000071size_t Process::GetMallocUsage() {
Reid Spencerbc1ee842004-12-20 16:06:44 +000072#if defined(HAVE_MALLINFO)
Reid Spencer721d9aa2004-12-20 00:59:28 +000073 struct mallinfo mi;
74 mi = ::mallinfo();
75 return mi.uordblks;
Chris Lattnerc590e9a2005-11-14 07:27:56 +000076#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
77 malloc_statistics_t Stats;
78 malloc_zone_statistics(malloc_default_zone(), &Stats);
79 return Stats.size_in_use; // darwin
Reid Spencerbc1ee842004-12-20 16:06:44 +000080#elif defined(HAVE_SBRK)
Reid Spencer721d9aa2004-12-20 00:59:28 +000081 // Note this is only an approximation and more closely resembles
82 // the value returned by mallinfo in the arena field.
Chris Lattner513a9542005-11-14 07:00:29 +000083 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
84 char *EndOfMemory = (char*)sbrk(0);
85 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
86 return EndOfMemory - StartOfMemory;
Reid Spencer721d9aa2004-12-20 00:59:28 +000087 else
88 return 0;
89#else
90#warning Cannot get malloc info on this platform
91 return 0;
92#endif
93}
94
Reid Spencer721d9aa2004-12-20 00:59:28 +000095void
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000096Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
Reid Spencer721d9aa2004-12-20 00:59:28 +000097 TimeValue& sys_time)
98{
99 elapsed = TimeValue::now();
Chris Lattner095cc372006-05-12 18:20:39 +0000100#if defined(HAVE_GETRUSAGE)
Reid Spencer721d9aa2004-12-20 00:59:28 +0000101 struct rusage usage;
102 ::getrusage(RUSAGE_SELF, &usage);
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000103 user_time = TimeValue(
104 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
105 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
Reid Spencer8b662892004-12-20 21:43:33 +0000106 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000107 sys_time = TimeValue(
108 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
109 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
Reid Spencer8b662892004-12-20 21:43:33 +0000110 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Reid Spencer721d9aa2004-12-20 00:59:28 +0000111#else
112#warning Cannot get usage times on this platform
113 user_time.seconds(0);
114 user_time.microseconds(0);
115 sys_time.seconds(0);
116 sys_time.microseconds(0);
117#endif
118}
119
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000120int Process::GetCurrentUserId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000121 return getuid();
122}
123
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000124int Process::GetCurrentGroupId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000125 return getgid();
126}
127
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000128#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begemane9563982008-04-12 00:47:46 +0000129#include <mach/mach.h>
130#endif
131
Reid Spencer68fdcc12004-12-27 06:17:27 +0000132// Some LLVM programs such as bugpoint produce core files as a normal part of
133// their operation. To prevent the disk from filling up, this function
134// does what's necessary to prevent their generation.
135void Process::PreventCoreFiles() {
136#if HAVE_SETRLIMIT
137 struct rlimit rlim;
138 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattner505f9c82006-05-14 18:53:09 +0000139 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencer68fdcc12004-12-27 06:17:27 +0000140#endif
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000141
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000142#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begemane9563982008-04-12 00:47:46 +0000143 // Disable crash reporting on Mac OS X 10.0-10.4
144
145 // get information about the original set of exception ports for the task
146 mach_msg_type_number_t Count = 0;
147 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
148 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
149 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
150 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000151 kern_return_t err =
Nate Begemane9563982008-04-12 00:47:46 +0000152 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
153 &Count, OriginalPorts, OriginalBehaviors,
154 OriginalFlavors);
155 if (err == KERN_SUCCESS) {
156 // replace each with MACH_PORT_NULL.
157 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000158 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begemane9563982008-04-12 00:47:46 +0000159 MACH_PORT_NULL, OriginalBehaviors[i],
160 OriginalFlavors[i]);
161 }
162
163 // Disable crash reporting on Mac OS X 10.5
Nate Begeman82b53cd2008-03-31 22:19:25 +0000164 signal(SIGABRT, _exit);
165 signal(SIGILL, _exit);
166 signal(SIGFPE, _exit);
167 signal(SIGSEGV, _exit);
168 signal(SIGBUS, _exit);
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000169#endif
Reid Spencer68fdcc12004-12-27 06:17:27 +0000170}
Reid Spencer721d9aa2004-12-20 00:59:28 +0000171
Reid Spencera01aade2005-01-01 22:29:26 +0000172bool Process::StandardInIsUserInput() {
Dan Gohmanec080462009-09-11 20:46:33 +0000173 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000174}
175
176bool Process::StandardOutIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000177 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000178}
179
180bool Process::StandardErrIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000181 return FileDescriptorIsDisplayed(STDERR_FILENO);
182}
183
184bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencera01aade2005-01-01 22:29:26 +0000185#if HAVE_ISATTY
Dan Gohmanec080462009-09-11 20:46:33 +0000186 return isatty(fd);
Duncan Sands740eb532009-09-06 10:53:22 +0000187#else
Reid Spencera01aade2005-01-01 22:29:26 +0000188 // If we don't have isatty, just return false.
189 return false;
Duncan Sands740eb532009-09-06 10:53:22 +0000190#endif
Reid Spencera01aade2005-01-01 22:29:26 +0000191}
Douglas Gregor01746742009-05-11 18:05:52 +0000192
193static unsigned getColumns(int FileID) {
194 // If COLUMNS is defined in the environment, wrap to that many columns.
195 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
196 int Columns = std::atoi(ColumnsStr);
197 if (Columns > 0)
198 return Columns;
199 }
200
201 unsigned Columns = 0;
202
Douglas Gregor071d73d2009-05-18 17:21:34 +0000203#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor01746742009-05-11 18:05:52 +0000204 // Try to determine the width of the terminal.
205 struct winsize ws;
206 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
207 Columns = ws.ws_col;
208#endif
209
210 return Columns;
211}
212
213unsigned Process::StandardOutColumns() {
214 if (!StandardOutIsDisplayed())
215 return 0;
216
217 return getColumns(1);
218}
219
220unsigned Process::StandardErrColumns() {
221 if (!StandardErrIsDisplayed())
222 return 0;
223
224 return getColumns(2);
225}
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000226
227static bool terminalHasColors() {
228 if (const char *term = std::getenv("TERM")) {
229 // Most modern terminals support ANSI escape sequences for colors.
230 // We could check terminfo, or have a list of known terms that support
231 // colors, but that would be overkill.
232 // The user can always ask for no colors by setting TERM to dumb, or
233 // using a commandline flag.
234 return strcmp(term, "dumb") != 0;
235 }
236 return false;
237}
238
Daniel Dunbar7d836582012-07-20 18:29:38 +0000239bool Process::FileDescriptorHasColors(int fd) {
240 // A file descriptor has colors if it is displayed and the terminal has
241 // colors.
242 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
243}
244
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000245bool Process::StandardOutHasColors() {
Daniel Dunbar7d836582012-07-20 18:29:38 +0000246 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000247}
248
249bool Process::StandardErrHasColors() {
Daniel Dunbar7d836582012-07-20 18:29:38 +0000250 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000251}
252
253bool Process::ColorNeedsFlush() {
254 // No, we use ANSI escape sequences.
255 return false;
256}
257
258#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
259
260#define ALLCOLORS(FGBG,BOLD) {\
261 COLOR(FGBG, "0", BOLD),\
262 COLOR(FGBG, "1", BOLD),\
263 COLOR(FGBG, "2", BOLD),\
264 COLOR(FGBG, "3", BOLD),\
265 COLOR(FGBG, "4", BOLD),\
266 COLOR(FGBG, "5", BOLD),\
267 COLOR(FGBG, "6", BOLD),\
268 COLOR(FGBG, "7", BOLD)\
269 }
270
Nuno Lopesec9d8b02009-12-23 17:48:10 +0000271static const char colorcodes[2][2][8][10] = {
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000272 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
273 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
274};
275
276const char *Process::OutputColor(char code, bool bold, bool bg) {
277 return colorcodes[bg?1:0][bold?1:0][code&7];
278}
279
280const char *Process::OutputBold(bool bg) {
281 return "\033[1m";
282}
283
Benjamin Kramer246de852012-04-16 08:56:50 +0000284const char *Process::OutputReverse() {
285 return "\033[7m";
286}
287
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000288const char *Process::ResetColor() {
289 return "\033[0m";
290}
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000291
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000292#if !defined(HAVE_ARC4RANDOM)
293static unsigned GetRandomNumberSeed() {
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000294 // Attempt to get the initial seed from /dev/urandom, if possible.
295 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
296 unsigned seed;
297 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000298 ::fclose(RandomSource);
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000299
300 // Return the seed if the read was successful.
301 if (count == 1)
302 return seed;
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000303 }
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000304
305 // Otherwise, swizzle the current time and the process ID to form a reasonable
306 // seed.
Chandler Carruth9b4aba82012-12-31 11:45:20 +0000307 TimeValue Now = TimeValue::now();
Daniel Dunbar2b8f3ba2012-05-08 20:38:00 +0000308 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000309}
310#endif
311
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000312unsigned llvm::sys::Process::GetRandomNumber() {
313#if defined(HAVE_ARC4RANDOM)
314 return arc4random();
315#else
NAKAMURA Takumidc736b02012-05-06 08:24:24 +0000316 static int x = (::srand(GetRandomNumberSeed()), 0);
317 (void)x;
NAKAMURA Takumi24cddd52012-05-06 08:24:18 +0000318 return ::rand();
319#endif
320}