blob: 7d8f6250136fd5ebe703a59077c862eda13da2d2 [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"
Rui Ueyama471d0c52013-09-10 19:45:51 +000016#include "llvm/ADT/StringRef.h"
Chandler Carruthcad7e5e2013-08-07 08:47:36 +000017#include "llvm/Support/Mutex.h"
18#include "llvm/Support/MutexGuard.h"
Daniel Dunbar5f1c9562012-05-08 20:38:00 +000019#include "llvm/Support/TimeValue.h"
Reid Spencerac38f3a2004-12-20 00:59:28 +000020#ifdef HAVE_SYS_TIME_H
21#include <sys/time.h>
22#endif
23#ifdef HAVE_SYS_RESOURCE_H
24#include <sys/resource.h>
25#endif
Eric Christopher22738d02012-08-06 20:52:18 +000026// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
27// <stdlib.h> instead. Unix.h includes this for us already.
28#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
29 !defined(__OpenBSD__) && !defined(__Bitrig__)
Reid Spencerac38f3a2004-12-20 00:59:28 +000030#include <malloc.h>
31#endif
Chris Lattner698fa762005-11-14 07:00:29 +000032#ifdef HAVE_MALLOC_MALLOC_H
33#include <malloc/malloc.h>
34#endif
Douglas Gregor15436612009-05-11 18:05:52 +000035#ifdef HAVE_SYS_IOCTL_H
36# include <sys/ioctl.h>
37#endif
Douglas Gregorb81294d2009-05-18 17:21:34 +000038#ifdef HAVE_TERMIOS_H
39# include <termios.h>
40#endif
Reid Spencer33b9d772004-09-11 04:56:56 +000041
42//===----------------------------------------------------------------------===//
43//=== WARNING: Implementation here must contain only generic UNIX code that
44//=== is guaranteed to work on *all* UNIX variants.
45//===----------------------------------------------------------------------===//
46
Chris Lattner2f107cf2006-09-14 06:01:41 +000047using namespace llvm;
Reid Spencer33b9d772004-09-11 04:56:56 +000048using namespace sys;
49
Chandler Carruth97683aa2012-12-31 11:17:50 +000050
51process::id_type self_process::get_id() {
52 return getpid();
53}
54
Chandler Carruthef7f9682013-01-04 23:19:55 +000055static std::pair<TimeValue, TimeValue> getRUsageTimes() {
56#if defined(HAVE_GETRUSAGE)
57 struct rusage RU;
58 ::getrusage(RUSAGE_SELF, &RU);
59 return std::make_pair(
60 TimeValue(
61 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
62 static_cast<TimeValue::NanoSecondsType>(
63 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
64 TimeValue(
65 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
66 static_cast<TimeValue::NanoSecondsType>(
67 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
68#else
69#warning Cannot get usage times on this platform
70 return std::make_pair(TimeValue(), TimeValue());
71#endif
72}
73
74TimeValue self_process::get_user_time() const {
Chandler Carruthb5429f42013-01-05 00:42:50 +000075#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
Chandler Carruthef7f9682013-01-04 23:19:55 +000076 // Try to get a high resolution CPU timer.
77 struct timespec TS;
78 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
79 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
80 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
81#endif
82
83 // Otherwise fall back to rusage based timing.
84 return getRUsageTimes().first;
85}
86
87TimeValue self_process::get_system_time() const {
88 // We can only collect system time by inspecting the results of getrusage.
89 return getRUsageTimes().second;
90}
91
NAKAMURA Takumi7a042342013-09-04 14:12:26 +000092// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
93// offset in mmap(3) should be aligned to the AllocationGranularity.
Chandler Carruth15dcad92012-12-31 23:23:35 +000094static unsigned getPageSize() {
NAKAMURA Takumi3bbbe2e2013-08-21 13:47:12 +000095#if defined(HAVE_GETPAGESIZE)
Owen Andersona83e8682009-08-19 21:48:34 +000096 const int page_size = ::getpagesize();
Reid Spencerac38f3a2004-12-20 00:59:28 +000097#elif defined(HAVE_SYSCONF)
Owen Andersona83e8682009-08-19 21:48:34 +000098 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencerac38f3a2004-12-20 00:59:28 +000099#else
100#warning Cannot get the page size on this machine
101#endif
Reid Spencer33b9d772004-09-11 04:56:56 +0000102 return static_cast<unsigned>(page_size);
103}
104
Chandler Carruth15dcad92012-12-31 23:23:35 +0000105// This constructor guaranteed to be run exactly once on a single thread, and
106// sets up various process invariants that can be queried cheaply from then on.
107self_process::self_process() : PageSize(getPageSize()) {
108}
109
110
Chris Lattner698fa762005-11-14 07:00:29 +0000111size_t Process::GetMallocUsage() {
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000112#if defined(HAVE_MALLINFO)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000113 struct mallinfo mi;
114 mi = ::mallinfo();
115 return mi.uordblks;
Chris Lattner16cbc6a2005-11-14 07:27:56 +0000116#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
117 malloc_statistics_t Stats;
118 malloc_zone_statistics(malloc_default_zone(), &Stats);
119 return Stats.size_in_use; // darwin
Reid Spencer1cf74ce2004-12-20 16:06:44 +0000120#elif defined(HAVE_SBRK)
Reid Spencerac38f3a2004-12-20 00:59:28 +0000121 // Note this is only an approximation and more closely resembles
122 // the value returned by mallinfo in the arena field.
Chris Lattner698fa762005-11-14 07:00:29 +0000123 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
124 char *EndOfMemory = (char*)sbrk(0);
125 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
126 return EndOfMemory - StartOfMemory;
Reid Spencerac38f3a2004-12-20 00:59:28 +0000127 else
128 return 0;
129#else
130#warning Cannot get malloc info on this platform
131 return 0;
132#endif
133}
134
Chandler Carruthef7f9682013-01-04 23:19:55 +0000135void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
136 TimeValue &sys_time) {
Reid Spencerac38f3a2004-12-20 00:59:28 +0000137 elapsed = TimeValue::now();
Chandler Carruthef7f9682013-01-04 23:19:55 +0000138 llvm::tie(user_time, sys_time) = getRUsageTimes();
Reid Spencerac38f3a2004-12-20 00:59:28 +0000139}
140
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000141#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-04-12 00:47:46 +0000142#include <mach/mach.h>
143#endif
144
Reid Spencercf15b872004-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 Lattnerf64397b2006-05-14 18:53:09 +0000152 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencercf15b872004-12-27 06:17:27 +0000153#endif
Chris Lattner2f107cf2006-09-14 06:01:41 +0000154
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000155#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
Nate Begeman48405152008-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. Spencer447762d2010-11-29 18:16:10 +0000164 kern_return_t err =
Nate Begeman48405152008-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. Spencer447762d2010-11-29 18:16:10 +0000171 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
Nate Begeman48405152008-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 Begemanf8be3832008-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 Lattner2f107cf2006-09-14 06:01:41 +0000182#endif
Reid Spencercf15b872004-12-27 06:17:27 +0000183}
Reid Spencerac38f3a2004-12-20 00:59:28 +0000184
Rui Ueyama471d0c52013-09-10 19:45:51 +0000185Optional<std::string> Process::GetEnv(StringRef Name) {
186 std::string NameStr = Name.str();
187 const char *Val = ::getenv(NameStr.c_str());
188 if (!Val)
189 return None;
190 return std::string(Val);
191}
192
Reid Spencer6f802ba2005-01-01 22:29:26 +0000193bool Process::StandardInIsUserInput() {
Dan Gohmane5929232009-09-11 20:46:33 +0000194 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000195}
196
197bool Process::StandardOutIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000198 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencer6f802ba2005-01-01 22:29:26 +0000199}
200
201bool Process::StandardErrIsDisplayed() {
Dan Gohmane5929232009-09-11 20:46:33 +0000202 return FileDescriptorIsDisplayed(STDERR_FILENO);
203}
204
205bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencer6f802ba2005-01-01 22:29:26 +0000206#if HAVE_ISATTY
Dan Gohmane5929232009-09-11 20:46:33 +0000207 return isatty(fd);
Duncan Sands44d423a2009-09-06 10:53:22 +0000208#else
Reid Spencer6f802ba2005-01-01 22:29:26 +0000209 // If we don't have isatty, just return false.
210 return false;
Duncan Sands44d423a2009-09-06 10:53:22 +0000211#endif
Reid Spencer6f802ba2005-01-01 22:29:26 +0000212}
Douglas Gregor15436612009-05-11 18:05:52 +0000213
214static unsigned getColumns(int FileID) {
215 // If COLUMNS is defined in the environment, wrap to that many columns.
216 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
217 int Columns = std::atoi(ColumnsStr);
218 if (Columns > 0)
219 return Columns;
220 }
221
222 unsigned Columns = 0;
223
Douglas Gregorb81294d2009-05-18 17:21:34 +0000224#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor15436612009-05-11 18:05:52 +0000225 // Try to determine the width of the terminal.
226 struct winsize ws;
227 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
228 Columns = ws.ws_col;
229#endif
230
231 return Columns;
232}
233
234unsigned Process::StandardOutColumns() {
235 if (!StandardOutIsDisplayed())
236 return 0;
237
238 return getColumns(1);
239}
240
241unsigned Process::StandardErrColumns() {
242 if (!StandardErrIsDisplayed())
243 return 0;
244
245 return getColumns(2);
246}
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000247
Chandler Carruth91219852013-08-12 10:40:11 +0000248#ifdef HAVE_TERMINFO
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000249// We manually declare these extern functions because finding the correct
Chandler Carruth91219852013-08-12 10:40:11 +0000250// headers from various terminfo, curses, or other sources is harder than
251// writing their specs down.
252extern "C" int setupterm(char *term, int filedes, int *errret);
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000253extern "C" struct term *set_curterm(struct term *termp);
254extern "C" int del_curterm(struct term *termp);
Chandler Carruth91219852013-08-12 10:40:11 +0000255extern "C" int tigetnum(char *capname);
256#endif
257
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000258static bool terminalHasColors(int fd) {
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000259#ifdef HAVE_TERMINFO
260 // First, acquire a global lock because these C routines are thread hostile.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000261 static sys::Mutex M;
262 MutexGuard G(M);
263
264 int errret = 0;
Chandler Carruth91219852013-08-12 10:40:11 +0000265 if (setupterm((char *)0, fd, &errret) != 0)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000266 // Regardless of why, if we can't get terminfo, we shouldn't try to print
267 // colors.
268 return false;
269
Chandler Carruthf11f1e42013-08-12 09:49:17 +0000270 // Test whether the terminal as set up supports color output. How to do this
271 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
272 // would be nice to avoid a dependency on curses proper when we can make do
273 // with a minimal terminfo parsing library. Also, we don't really care whether
274 // the terminal supports the curses-specific color changing routines, merely
275 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
276 // strategy here is just to query the baseline colors capability and if it
277 // supports colors at all to assume it will translate the escape codes into
278 // whatever range of colors it does support. We can add more detailed tests
279 // here if users report them as necessary.
280 //
281 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
282 // the terminfo says that no colors are supported.
Chandler Carruth67ff8b72013-08-18 01:20:32 +0000283 bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
284
285 // Now extract the structure allocated by setupterm and free its memory
286 // through a really silly dance.
287 struct term *termp = set_curterm((struct term *)0);
288 (void)del_curterm(termp); // Drop any errors here.
289
290 // Return true if we found a color capabilities for the current terminal.
291 if (HasColors)
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000292 return true;
293#endif
294
295 // Otherwise, be conservative.
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000296 return false;
297}
298
Daniel Dunbar712de822012-07-20 18:29:38 +0000299bool Process::FileDescriptorHasColors(int fd) {
300 // A file descriptor has colors if it is displayed and the terminal has
301 // colors.
Chandler Carruthcad7e5e2013-08-07 08:47:36 +0000302 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
Daniel Dunbar712de822012-07-20 18:29:38 +0000303}
304
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000305bool Process::StandardOutHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000306 return FileDescriptorHasColors(STDOUT_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000307}
308
309bool Process::StandardErrHasColors() {
Daniel Dunbar712de822012-07-20 18:29:38 +0000310 return FileDescriptorHasColors(STDERR_FILENO);
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000311}
312
313bool Process::ColorNeedsFlush() {
314 // No, we use ANSI escape sequences.
315 return false;
316}
317
318#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
319
320#define ALLCOLORS(FGBG,BOLD) {\
321 COLOR(FGBG, "0", BOLD),\
322 COLOR(FGBG, "1", BOLD),\
323 COLOR(FGBG, "2", BOLD),\
324 COLOR(FGBG, "3", BOLD),\
325 COLOR(FGBG, "4", BOLD),\
326 COLOR(FGBG, "5", BOLD),\
327 COLOR(FGBG, "6", BOLD),\
328 COLOR(FGBG, "7", BOLD)\
329 }
330
Nuno Lopes129819d2009-12-23 17:48:10 +0000331static const char colorcodes[2][2][8][10] = {
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000332 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
333 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
334};
335
336const char *Process::OutputColor(char code, bool bold, bool bg) {
337 return colorcodes[bg?1:0][bold?1:0][code&7];
338}
339
340const char *Process::OutputBold(bool bg) {
341 return "\033[1m";
342}
343
Benjamin Kramer13d16f32012-04-16 08:56:50 +0000344const char *Process::OutputReverse() {
345 return "\033[7m";
346}
347
Torok Edwin9b5a47f2009-06-04 07:09:50 +0000348const char *Process::ResetColor() {
349 return "\033[0m";
350}
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000351
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000352#if !defined(HAVE_ARC4RANDOM)
353static unsigned GetRandomNumberSeed() {
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000354 // Attempt to get the initial seed from /dev/urandom, if possible.
355 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
356 unsigned seed;
357 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000358 ::fclose(RandomSource);
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000359
360 // Return the seed if the read was successful.
361 if (count == 1)
362 return seed;
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000363 }
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000364
365 // Otherwise, swizzle the current time and the process ID to form a reasonable
366 // seed.
Chandler Carruth5473dfb2012-12-31 11:45:20 +0000367 TimeValue Now = TimeValue::now();
Daniel Dunbar5f1c9562012-05-08 20:38:00 +0000368 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000369}
370#endif
371
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000372unsigned llvm::sys::Process::GetRandomNumber() {
373#if defined(HAVE_ARC4RANDOM)
374 return arc4random();
375#else
NAKAMURA Takumi7bec7412012-05-06 08:24:24 +0000376 static int x = (::srand(GetRandomNumberSeed()), 0);
377 (void)x;
NAKAMURA Takumi54acb282012-05-06 08:24:18 +0000378 return ::rand();
379#endif
380}