blob: b83f5079ce00bd2c647a97b93a8a1509000b8cb1 [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
52
Michael J. Spencer447762d2010-11-29 18:16:10 +000053unsigned
54Process::GetPageSize()
Reid Spencerac38f3a2004-12-20 00:59:28 +000055{
Jay Foadc1fca9fb2009-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 Andersona83e8682009-08-19 21:48:34 +000060 const int page_size = 0x1000;
Jay Foadc1fca9fb2009-05-23 17:57:59 +000061#elif defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000062 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000063#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +000064 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +000065#else
66#warning Cannot get the page size on this machine
67#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000068 return static_cast<unsigned>(page_size);
69}
70
Chris Lattner698fa762005-11-14 07:00:29 +000071size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +000072#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +000073 struct mallinfo mi;
74 mi = ::mallinfo();
75 return mi.uordblks;
Chris Lattner16cbc6a2005-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 Spencer1cf74ce2004-12-20 16:06:44 +000080#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-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 Lattner698fa762005-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 Spencerac38f3a2004-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
Jeff Cohen1a26d152005-01-08 20:15:57 +000095size_t
Reid Spencerac38f3a2004-12-20 00:59:28 +000096Process::GetTotalMemoryUsage()
97{
Reid Spencer1cf74ce2004-12-20 16:06:44 +000098#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +000099 struct mallinfo mi = ::mallinfo();
100 return mi.uordblks + mi.hblkhd;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000101#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
102 malloc_statistics_t Stats;
103 malloc_zone_statistics(malloc_default_zone(), &Stats);
104 return Stats.size_allocated; // darwin
Edward O'Callaghan8227b052009-10-12 04:57:20 +0000105#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
Reid Spencer8005e662004-12-20 16:33:37 +0000106 struct rusage usage;
107 ::getrusage(RUSAGE_SELF, &usage);
108 return usage.ru_maxrss;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000109#else
110#warning Cannot get total memory size on this platform
111 return 0;
112#endif
113}
114
115void
Michael J. Spencer447762d2010-11-29 18:16:10 +0000116Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
Reid Spencerac38f3a2004-12-20 00:59:28 +0000117 TimeValue& sys_time)
118{
119 elapsed = TimeValue::now();
Chris Lattner227d4422006-05-12 18:20:39 +0000120#if defined(HAVE_GETRUSAGE)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000121 struct rusage usage;
122 ::getrusage(RUSAGE_SELF, &usage);
Michael J. Spencer447762d2010-11-29 18:16:10 +0000123 user_time = TimeValue(
124 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
125 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
Reid Spencerd4c69882004-12-20 21:43:33 +0000126 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Michael J. Spencer447762d2010-11-29 18:16:10 +0000127 sys_time = TimeValue(
128 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
129 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
Reid Spencerd4c69882004-12-20 21:43:33 +0000130 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
Reid Spencerac38f3a2004-12-20 00:59:28 +0000131#else
132#warning Cannot get usage times on this platform
133 user_time.seconds(0);
134 user_time.microseconds(0);
135 sys_time.seconds(0);
136 sys_time.microseconds(0);
137#endif
138}
139
Chris Lattner2f107cf2006-09-14 06:01:41 +0000140int Process::GetCurrentUserId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000141 return getuid();
142}
143
Chris Lattner2f107cf2006-09-14 06:01:41 +0000144int Process::GetCurrentGroupId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000145 return getgid();
146}
147
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000148#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000149#include <mach/mach.h>
150#endif
151
Reid Spencercf15b872004-12-27 06:17:27 +0000152// Some LLVM programs such as bugpoint produce core files as a normal part of
153// their operation. To prevent the disk from filling up, this function
154// does what's necessary to prevent their generation.
155void Process::PreventCoreFiles() {
156#if HAVE_SETRLIMIT
157 struct rlimit rlim;
158 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000159 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000160#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000161
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000162#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000163 // Disable crash reporting on Mac OS X 10.0-10.4
164
165 // get information about the original set of exception ports for the task
166 mach_msg_type_number_t Count = 0;
167 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
168 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
169 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
170 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000171 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000172 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
173 &Count, OriginalPorts, OriginalBehaviors,
174 OriginalFlavors);
175 if (err == KERN_SUCCESS) {
176 // replace each with MACH_PORT_NULL.
177 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000178 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000179 MACH_PORT_NULL, OriginalBehaviors[i],
180 OriginalFlavors[i]);
181 }
182
183 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000184 signal(SIGABRT, _exit);
185 signal(SIGILL, _exit);
186 signal(SIGFPE, _exit);
187 signal(SIGSEGV, _exit);
188 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000189#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000190}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000191
Reid Spencer6f802ba2005-01-01 22:29:26 +0000192bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000193 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000194}
195
196bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000197 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000198}
199
200bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000201 return FileDescriptorIsDisplayed(STDERR_FILENO);
202}
203
204bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000205#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000206 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000207#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000208 // If we don't have isatty, just return false.
209 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000210#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000211}
Douglas Gregor15436612009-05-11 18:05:52 +0000212
213static unsigned getColumns(int FileID) {
214 // If COLUMNS is defined in the environment, wrap to that many columns.
215 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
216 int Columns = std::atoi(ColumnsStr);
217 if (Columns > 0)
218 return Columns;
219 }
220
221 unsigned Columns = 0;
222
Douglas Gregorb81294d2009-05-18 17:21:34 +0000223#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000224 // Try to determine the width of the terminal.
225 struct winsize ws;
226 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
227 Columns = ws.ws_col;
228#endif
229
230 return Columns;
231}
232
233unsigned Process::StandardOutColumns() {
234 if (!StandardOutIsDisplayed())
235 return 0;
236
237 return getColumns(1);
238}
239
240unsigned Process::StandardErrColumns() {
241 if (!StandardErrIsDisplayed())
242 return 0;
243
244 return getColumns(2);
245}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000246
247static bool terminalHasColors() {
248 if (const char *term = std::getenv("TERM")) {
249 // Most modern terminals support ANSI escape sequences for colors.
250 // We could check terminfo, or have a list of known terms that support
251 // colors, but that would be overkill.
252 // The user can always ask for no colors by setting TERM to dumb, or
253 // using a commandline flag.
254 return strcmp(term, "dumb") != 0;
255 }
256 return false;
257}
258
Daniel Dunbar712de822012-07-20 18:29:38 +0000259bool Process::FileDescriptorHasColors(int fd) {
260 // A file descriptor has colors if it is displayed and the terminal has
261 // colors.
262 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
263}
264
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000265bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000266 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000267}
268
269bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000270 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000271}
272
273bool Process::ColorNeedsFlush() {
274 // No, we use ANSI escape sequences.
275 return false;
276}
277
278#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
279
280#define ALLCOLORS(FGBG,BOLD) {\
281 COLOR(FGBG, "0", BOLD),\
282 COLOR(FGBG, "1", BOLD),\
283 COLOR(FGBG, "2", BOLD),\
284 COLOR(FGBG, "3", BOLD),\
285 COLOR(FGBG, "4", BOLD),\
286 COLOR(FGBG, "5", BOLD),\
287 COLOR(FGBG, "6", BOLD),\
288 COLOR(FGBG, "7", BOLD)\
289 }
290
Nuno Lopes129819d2009-12-23 17:48:10 +0000291static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000292 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
293 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
294};
295
296const char *Process::OutputColor(char code, bool bold, bool bg) {
297 return colorcodes[bg?1:0][bold?1:0][code&7];
298}
299
300const char *Process::OutputBold(bool bg) {
301 return "\033[1m";
302}
303
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000304const char *Process::OutputReverse() {
305 return "\033[7m";
306}
307
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000308const char *Process::ResetColor() {
309 return "\033[0m";
310}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000311
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000312#if !defined(HAVE_ARC4RANDOM)
313static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000314 // Attempt to get the initial seed from /dev/urandom, if possible.
315 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
316 unsigned seed;
317 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000318 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000319
320 // Return the seed if the read was successful.
321 if (count == 1)
322 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000323 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000324
325 // Otherwise, swizzle the current time and the process ID to form a reasonable
326 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000327 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000328 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000329}
330#endif
331
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000332unsigned llvm::sys::Process::GetRandomNumber() {
333#if defined(HAVE_ARC4RANDOM)
334 return arc4random();
335#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000336 static int x = (::srand(GetRandomNumberSeed()), 0);
337 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000338 return ::rand();
339#endif
340}