blob: 0a797f6979e5814a43b79340fd272d2442a8d6b5 [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"
Chandler Carruthcad7e5e2013-08-07 08:47:36 +000016#include "llvm/Support/Mutex.h"
17#include "llvm/Support/MutexGuard.h"
Daniel Dunbar5f1c9562012-05-08 20:38:00 +000018#include "llvm/Support/TimeValue.h"
Reid Spencerac38f3a2004-12-20 00:59:28 +000019#ifdef HAVE_SYS_TIME_H
20#include <sys/time.h>
21#endif
22#ifdef HAVE_SYS_RESOURCE_H
23#include <sys/resource.h>
24#endif
Eric Christopher22738d02012-08-06 20:52:18 +000025// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
26// <stdlib.h> instead. Unix.h includes this for us already.
27#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
28 !defined(__OpenBSD__) && !defined(__Bitrig__)
Reid Spencerac38f3a2004-12-20 00:59:28 +000029#include <malloc.h>
30#endif
Chris Lattner698fa762005-11-14 07:00:29 +000031#ifdef HAVE_MALLOC_MALLOC_H
32#include <malloc/malloc.h>
33#endif
Douglas Gregor15436612009-05-11 18:05:52 +000034#ifdef HAVE_SYS_IOCTL_H
35# include <sys/ioctl.h>
36#endif
Douglas Gregorb81294d2009-05-18 17:21:34 +000037#ifdef HAVE_TERMIOS_H
38# include <termios.h>
39#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000040
Chandler Carruthcad7e5e2013-08-07 08:47:36 +000041// See if we can use curses to detect information about a terminal when
42// connected to one.
43#ifdef HAVE_CURSES
44# if defined(HAVE_CURSES_H)
45# include <curses.h>
46# elif defined(HAVE_NCURSES_H)
47# include <ncurses.h>
48# elif defined(HAVE_NCURSESW_H)
49# include <ncursesw.h>
50# elif defined(HAVE_NCURSES_CURSES_H)
51# include <ncurses/curses.h>
52# elif defined(HAVE_NCURSESW_CURSES_H)
53# include <ncursesw/curses.h>
54# else
55# error Have a curses library but unable to find a curses header!
56# endif
57# include <term.h>
58#endif
59
Reid Spencer33b9d772004-09-11 04:56:56 +000060//===----------------------------------------------------------------------===//
61//=== WARNING: Implementation here must contain only generic UNIX code that
62//=== is guaranteed to work on *all* UNIX variants.
63//===----------------------------------------------------------------------===//
64
Chris Lattner2f107cf2006-09-14 06:01:41 +000065using namespace llvm;
Reid Spencer33b9d772004-09-11 04:56:56 +000066using namespace sys;
67
Chandler Carruth97683aa2012-12-31 11:17:50 +000068
69process::id_type self_process::get_id() {
70 return getpid();
71}
72
Chandler Carruthef7f9682013-01-04 23:19:55 +000073static std::pair<TimeValue, TimeValue> getRUsageTimes() {
74#if defined(HAVE_GETRUSAGE)
75 struct rusage RU;
76 ::getrusage(RUSAGE_SELF, &RU);
77 return std::make_pair(
78 TimeValue(
79 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
80 static_cast<TimeValue::NanoSecondsType>(
81 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
82 TimeValue(
83 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
84 static_cast<TimeValue::NanoSecondsType>(
85 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
86#else
87#warning Cannot get usage times on this platform
88 return std::make_pair(TimeValue(), TimeValue());
89#endif
90}
91
92TimeValue self_process::get_user_time() const {
Chandler Carruthb5429f42013-01-05 00:42:50 +000093#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
Chandler Carruthef7f9682013-01-04 23:19:55 +000094 // Try to get a high resolution CPU timer.
95 struct timespec TS;
96 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
97 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
98 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
99#endif
100
101 // Otherwise fall back to rusage based timing.
102 return getRUsageTimes().first;
103}
104
105TimeValue self_process::get_system_time() const {
106 // We can only collect system time by inspecting the results of getrusage.
107 return getRUsageTimes().second;
108}
109
Chandler Carruth15dcad92012-12-31 23:23:35 +0000110static unsigned getPageSize() {
Jay Foadc1fca9fb2009-05-23 17:57:59 +0000111#if defined(__CYGWIN__)
112 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
113 // memory protection and mmap() is 4k.
114 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
Owen Andersona83e8682009-08-19 21:48:34 +0000115 const int page_size = 0x1000;
Jay Foadc1fca9fb2009-05-23 17:57:59 +0000116#elif defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +0000117 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000118#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +0000119 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +0000120#else
121#warning Cannot get the page size on this machine
122#endif
Reid Spencer33b9d772004-09-11 04:56:56 +0000123 return static_cast<unsigned>(page_size);
124}
125
Chandler Carruth15dcad92012-12-31 23:23:35 +0000126// This constructor guaranteed to be run exactly once on a single thread, and
127// sets up various process invariants that can be queried cheaply from then on.
128self_process::self_process() : PageSize(getPageSize()) {
129}
130
131
Chris Lattner698fa762005-11-14 07:00:29 +0000132size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000133#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000134 struct mallinfo mi;
135 mi = ::mallinfo();
136 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000137#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
138 malloc_statistics_t Stats;
139 malloc_zone_statistics(malloc_default_zone(), &Stats);
140 return Stats.size_in_use; // darwin
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000141#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000142 // Note this is only an approximation and more closely resembles
143 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +0000144 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
145 char *EndOfMemory = (char*)sbrk(0);
146 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
147 return EndOfMemory - StartOfMemory;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000148 else
149 return 0;
150#else
151#warning Cannot get malloc info on this platform
152 return 0;
153#endif
154}
155
Chandler Carruthef7f9682013-01-04 23:19:55 +0000156void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
157 TimeValue &sys_time) {
Reid Spencerac38f3a2004-12-20 00:59:28 +0000158 elapsed = TimeValue::now();
Chandler Carruthef7f9682013-01-04 23:19:55 +0000159 llvm::tie(user_time, sys_time) = getRUsageTimes();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000160}
161
Chris Lattner2f107cf2006-09-14 06:01:41 +0000162int Process::GetCurrentUserId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000163 return getuid();
164}
165
Chris Lattner2f107cf2006-09-14 06:01:41 +0000166int Process::GetCurrentGroupId() {
Reid Spencer2d45e252005-04-21 16:12:57 +0000167 return getgid();
168}
169
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000170#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000171#include <mach/mach.h>
172#endif
173
Reid Spencercf15b872004-12-27 06:17:27 +0000174// Some LLVM programs such as bugpoint produce core files as a normal part of
175// their operation. To prevent the disk from filling up, this function
176// does what's necessary to prevent their generation.
177void Process::PreventCoreFiles() {
178#if HAVE_SETRLIMIT
179 struct rlimit rlim;
180 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattnerf64397b2006-05-14 18:53:09 +0000181 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000182#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000183
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000184#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000185 // Disable crash reporting on Mac OS X 10.0-10.4
186
187 // get information about the original set of exception ports for the task
188 mach_msg_type_number_t Count = 0;
189 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
190 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
191 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
192 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
Michael J. Spencer447762d2010-11-29 18:16:10 +0000193 kern_return_t err =
Nate Begeman48405152008-04-12 00:47:46 +0000194 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
195 &Count, OriginalPorts, OriginalBehaviors,
196 OriginalFlavors);
197 if (err == KERN_SUCCESS) {
198 // replace each with MACH_PORT_NULL.
199 for (unsigned i = 0; i != Count; ++i)
Michael J. Spencer447762d2010-11-29 18:16:10 +0000200 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-04-12 00:47:46 +0000201 MACH_PORT_NULL, OriginalBehaviors[i],
202 OriginalFlavors[i]);
203 }
204
205 // Disable crash reporting on Mac OS X 10.5
Nate Begemanf8be3832008-03-31 22:19:25 +0000206 signal(SIGABRT, _exit);
207 signal(SIGILL, _exit);
208 signal(SIGFPE, _exit);
209 signal(SIGSEGV, _exit);
210 signal(SIGBUS, _exit);
Chris Lattner2f107cf2006-09-14 06:01:41 +0000211#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000212}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000213
Reid Spencer6f802ba2005-01-01 22:29:26 +0000214bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000215 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000216}
217
218bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000219 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000220}
221
222bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000223 return FileDescriptorIsDisplayed(STDERR_FILENO);
224}
225
226bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000227#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000228 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000229#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000230 // If we don't have isatty, just return false.
231 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000232#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000233}
Douglas Gregor15436612009-05-11 18:05:52 +0000234
235static unsigned getColumns(int FileID) {
236 // If COLUMNS is defined in the environment, wrap to that many columns.
237 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
238 int Columns = std::atoi(ColumnsStr);
239 if (Columns > 0)
240 return Columns;
241 }
242
243 unsigned Columns = 0;
244
Douglas Gregorb81294d2009-05-18 17:21:34 +0000245#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000246 // Try to determine the width of the terminal.
247 struct winsize ws;
248 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
249 Columns = ws.ws_col;
250#endif
251
252 return Columns;
253}
254
255unsigned Process::StandardOutColumns() {
256 if (!StandardOutIsDisplayed())
257 return 0;
258
259 return getColumns(1);
260}
261
262unsigned Process::StandardErrColumns() {
263 if (!StandardErrIsDisplayed())
264 return 0;
265
266 return getColumns(2);
267}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000268
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000269static bool terminalHasColors(int fd) {
270#ifdef HAVE_CURSES
271 // First, acquire a global lock because the curses C routines are thread
272 // hostile.
273 static sys::Mutex M;
274 MutexGuard G(M);
275
276 int errret = 0;
277 if (setupterm((char *)0, fd, &errret) != OK)
278 // Regardless of why, if we can't get terminfo, we shouldn't try to print
279 // colors.
280 return false;
281
282 // Test whether the terminal as set up supports color output.
283 if (has_colors() == TRUE)
284 return true;
285#endif
286
287 // Otherwise, be conservative.
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000288 return false;
289}
290
Daniel Dunbar712de822012-07-20 18:29:38 +0000291bool Process::FileDescriptorHasColors(int fd) {
292 // A file descriptor has colors if it is displayed and the terminal has
293 // colors.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000294 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
Daniel Dunbar712de822012-07-20 18:29:38 +0000295}
296
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000297bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000298 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000299}
300
301bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000302 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000303}
304
305bool Process::ColorNeedsFlush() {
306 // No, we use ANSI escape sequences.
307 return false;
308}
309
310#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
311
312#define ALLCOLORS(FGBG,BOLD) {\
313 COLOR(FGBG, "0", BOLD),\
314 COLOR(FGBG, "1", BOLD),\
315 COLOR(FGBG, "2", BOLD),\
316 COLOR(FGBG, "3", BOLD),\
317 COLOR(FGBG, "4", BOLD),\
318 COLOR(FGBG, "5", BOLD),\
319 COLOR(FGBG, "6", BOLD),\
320 COLOR(FGBG, "7", BOLD)\
321 }
322
Nuno Lopes129819d2009-12-23 17:48:10 +0000323static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000324 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
325 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
326};
327
328const char *Process::OutputColor(char code, bool bold, bool bg) {
329 return colorcodes[bg?1:0][bold?1:0][code&7];
330}
331
332const char *Process::OutputBold(bool bg) {
333 return "\033[1m";
334}
335
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000336const char *Process::OutputReverse() {
337 return "\033[7m";
338}
339
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000340const char *Process::ResetColor() {
341 return "\033[0m";
342}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000343
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000344#if !defined(HAVE_ARC4RANDOM)
345static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000346 // Attempt to get the initial seed from /dev/urandom, if possible.
347 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
348 unsigned seed;
349 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000350 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000351
352 // Return the seed if the read was successful.
353 if (count == 1)
354 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000355 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000356
357 // Otherwise, swizzle the current time and the process ID to form a reasonable
358 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000359 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000360 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000361}
362#endif
363
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000364unsigned llvm::sys::Process::GetRandomNumber() {
365#if defined(HAVE_ARC4RANDOM)
366 return arc4random();
367#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000368 static int x = (::srand(GetRandomNumberSeed()), 0);
369 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000370 return ::rand();
371#endif
372}