LLVM  14.0.0git
Process.inc
Go to the documentation of this file.
1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides the generic Unix implementation of the Process class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Unix.h"
14 #include "llvm/ADT/Hashing.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Config/config.h"
18 #include <mutex>
19 #if HAVE_FCNTL_H
20 #include <fcntl.h>
21 #endif
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25 #ifdef HAVE_SYS_RESOURCE_H
26 #include <sys/resource.h>
27 #endif
28 #ifdef HAVE_SYS_STAT_H
29 #include <sys/stat.h>
30 #endif
31 #if HAVE_SIGNAL_H
32 #include <signal.h>
33 #endif
34 #if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
35 #include <malloc.h>
36 #endif
37 #if defined(HAVE_MALLCTL)
38 #include <malloc_np.h>
39 #endif
40 #ifdef HAVE_MALLOC_MALLOC_H
41 #include <malloc/malloc.h>
42 #endif
43 #ifdef HAVE_SYS_IOCTL_H
44 # include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_TERMIOS_H
47 # include <termios.h>
48 #endif
49 
50 //===----------------------------------------------------------------------===//
51 //=== WARNING: Implementation here must contain only generic UNIX code that
52 //=== is guaranteed to work on *all* UNIX variants.
53 //===----------------------------------------------------------------------===//
54 
55 using namespace llvm;
56 using namespace sys;
57 
58 static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
59 #if defined(HAVE_GETRUSAGE)
60  struct rusage RU;
61  ::getrusage(RUSAGE_SELF, &RU);
62  return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
63 #else
64 #warning Cannot get usage times on this platform
66 #endif
67 }
68 
70  static_assert(sizeof(Pid) >= sizeof(pid_t),
71  "Process::Pid should be big enough to store pid_t");
72  return Pid(::getpid());
73 }
74 
75 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
76 // offset in mmap(3) should be aligned to the AllocationGranularity.
78 #if defined(HAVE_GETPAGESIZE)
79  static const int page_size = ::getpagesize();
80 #elif defined(HAVE_SYSCONF)
81  static long page_size = ::sysconf(_SC_PAGE_SIZE);
82 #else
83 #error Cannot get the page size on this machine
84 #endif
85  if (page_size == -1)
86  return errorCodeToError(std::error_code(errno, std::generic_category()));
87 
88  return static_cast<unsigned>(page_size);
89 }
90 
91 size_t Process::GetMallocUsage() {
92 #if defined(HAVE_MALLINFO2)
93  struct mallinfo2 mi;
94  mi = ::mallinfo2();
95  return mi.uordblks;
96 #elif defined(HAVE_MALLINFO)
97  struct mallinfo mi;
98  mi = ::mallinfo();
99  return mi.uordblks;
100 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
101  malloc_statistics_t Stats;
102  malloc_zone_statistics(malloc_default_zone(), &Stats);
103  return Stats.size_in_use; // darwin
104 #elif defined(HAVE_MALLCTL)
105  size_t alloc, sz;
106  sz = sizeof(size_t);
107  if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
108  return alloc;
109  return 0;
110 #elif defined(HAVE_SBRK)
111  // Note this is only an approximation and more closely resembles
112  // the value returned by mallinfo in the arena field.
113  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
114  char *EndOfMemory = (char*)sbrk(0);
115  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
116  return EndOfMemory - StartOfMemory;
117  return 0;
118 #else
119 #warning Cannot get malloc info on this platform
120  return 0;
121 #endif
122 }
123 
124 void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
125  std::chrono::nanoseconds &sys_time) {
126  elapsed = std::chrono::system_clock::now();
127  std::tie(user_time, sys_time) = getRUsageTimes();
128 }
129 
130 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
131 #include <mach/mach.h>
132 #endif
133 
134 // Some LLVM programs such as bugpoint produce core files as a normal part of
135 // their operation. To prevent the disk from filling up, this function
136 // does what's necessary to prevent their generation.
138 #if HAVE_SETRLIMIT
139  struct rlimit rlim;
140  rlim.rlim_cur = rlim.rlim_max = 0;
141  setrlimit(RLIMIT_CORE, &rlim);
142 #endif
143 
144 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
145  // Disable crash reporting on Mac OS X 10.0-10.4
146 
147  // get information about the original set of exception ports for the task
148  mach_msg_type_number_t Count = 0;
149  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
150  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
151  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
152  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
153  kern_return_t err =
154  task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
155  &Count, OriginalPorts, OriginalBehaviors,
156  OriginalFlavors);
157  if (err == KERN_SUCCESS) {
158  // replace each with MACH_PORT_NULL.
159  for (unsigned i = 0; i != Count; ++i)
160  task_set_exception_ports(mach_task_self(), OriginalMasks[i],
161  MACH_PORT_NULL, OriginalBehaviors[i],
162  OriginalFlavors[i]);
163  }
164 
165  // Disable crash reporting on Mac OS X 10.5
166  signal(SIGABRT, _exit);
167  signal(SIGILL, _exit);
168  signal(SIGFPE, _exit);
169  signal(SIGSEGV, _exit);
170  signal(SIGBUS, _exit);
171 #endif
172 
173  coreFilesPrevented = true;
174 }
175 
177  std::string NameStr = Name.str();
178  const char *Val = ::getenv(NameStr.c_str());
179  if (!Val)
180  return None;
181  return std::string(Val);
182 }
183 
184 namespace {
185 class FDCloser {
186 public:
187  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
188  void keepOpen() { KeepOpen = true; }
189  ~FDCloser() {
190  if (!KeepOpen && FD >= 0)
191  ::close(FD);
192  }
193 
194 private:
195  FDCloser(const FDCloser &) = delete;
196  void operator=(const FDCloser &) = delete;
197 
198  int &FD;
199  bool KeepOpen;
200 };
201 }
202 
203 std::error_code Process::FixupStandardFileDescriptors() {
204  int NullFD = -1;
205  FDCloser FDC(NullFD);
206  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
207  for (int StandardFD : StandardFDs) {
208  struct stat st;
209  errno = 0;
210  if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
211  assert(errno && "expected errno to be set if fstat failed!");
212  // fstat should return EBADF if the file descriptor is closed.
213  if (errno != EBADF)
214  return std::error_code(errno, std::generic_category());
215  }
216  // if fstat succeeds, move on to the next FD.
217  if (!errno)
218  continue;
219  assert(errno == EBADF && "expected errno to have EBADF at this point!");
220 
221  if (NullFD < 0) {
222  // Call ::open in a lambda to avoid overload resolution in
223  // RetryAfterSignal when open is overloaded, such as in Bionic.
224  auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
225  if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
226  return std::error_code(errno, std::generic_category());
227  }
228 
229  if (NullFD == StandardFD)
230  FDC.keepOpen();
231  else if (dup2(NullFD, StandardFD) < 0)
232  return std::error_code(errno, std::generic_category());
233  }
234  return std::error_code();
235 }
236 
237 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
238  // Create a signal set filled with *all* signals.
239  sigset_t FullSet, SavedSet;
240  if (sigfillset(&FullSet) < 0 || sigfillset(&SavedSet) < 0)
241  return std::error_code(errno, std::generic_category());
242 
243  // Atomically swap our current signal mask with a full mask.
244 #if LLVM_ENABLE_THREADS
245  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
246  return std::error_code(EC, std::generic_category());
247 #else
248  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
249  return std::error_code(errno, std::generic_category());
250 #endif
251  // Attempt to close the file descriptor.
252  // We need to save the error, if one occurs, because our subsequent call to
253  // pthread_sigmask might tamper with errno.
254  int ErrnoFromClose = 0;
255  if (::close(FD) < 0)
256  ErrnoFromClose = errno;
257  // Restore the signal mask back to what we saved earlier.
258  int EC = 0;
259 #if LLVM_ENABLE_THREADS
260  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
261 #else
262  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
263  EC = errno;
264 #endif
265  // The error code from close takes precedence over the one from
266  // pthread_sigmask.
267  if (ErrnoFromClose)
268  return std::error_code(ErrnoFromClose, std::generic_category());
269  return std::error_code(EC, std::generic_category());
270 }
271 
273  return FileDescriptorIsDisplayed(STDIN_FILENO);
274 }
275 
277  return FileDescriptorIsDisplayed(STDOUT_FILENO);
278 }
279 
281  return FileDescriptorIsDisplayed(STDERR_FILENO);
282 }
283 
285 #if HAVE_ISATTY
286  return isatty(fd);
287 #else
288  // If we don't have isatty, just return false.
289  return false;
290 #endif
291 }
292 
293 static unsigned getColumns() {
294  // If COLUMNS is defined in the environment, wrap to that many columns.
295  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
296  int Columns = std::atoi(ColumnsStr);
297  if (Columns > 0)
298  return Columns;
299  }
300 
301  // We used to call ioctl TIOCGWINSZ to determine the width. It is considered
302  // unuseful.
303  return 0;
304 }
305 
306 unsigned Process::StandardOutColumns() {
307  if (!StandardOutIsDisplayed())
308  return 0;
309 
310  return getColumns();
311 }
312 
313 unsigned Process::StandardErrColumns() {
314  if (!StandardErrIsDisplayed())
315  return 0;
316 
317  return getColumns();
318 }
319 
320 #ifdef LLVM_ENABLE_TERMINFO
321 // We manually declare these extern functions because finding the correct
322 // headers from various terminfo, curses, or other sources is harder than
323 // writing their specs down.
324 extern "C" int setupterm(char *term, int filedes, int *errret);
325 extern "C" struct term *set_curterm(struct term *termp);
326 extern "C" int del_curterm(struct term *termp);
327 extern "C" int tigetnum(char *capname);
328 #endif
329 
330 #ifdef LLVM_ENABLE_TERMINFO
331 static ManagedStatic<std::mutex> TermColorMutex;
332 #endif
333 
334 static bool terminalHasColors(int fd) {
335 #ifdef LLVM_ENABLE_TERMINFO
336  // First, acquire a global lock because these C routines are thread hostile.
337  std::lock_guard<std::mutex> G(*TermColorMutex);
338 
339  struct term *previous_term = set_curterm(nullptr);
340  int errret = 0;
341  if (setupterm(nullptr, fd, &errret) != 0)
342  // Regardless of why, if we can't get terminfo, we shouldn't try to print
343  // colors.
344  return false;
345 
346  // Test whether the terminal as set up supports color output. How to do this
347  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
348  // would be nice to avoid a dependency on curses proper when we can make do
349  // with a minimal terminfo parsing library. Also, we don't really care whether
350  // the terminal supports the curses-specific color changing routines, merely
351  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
352  // strategy here is just to query the baseline colors capability and if it
353  // supports colors at all to assume it will translate the escape codes into
354  // whatever range of colors it does support. We can add more detailed tests
355  // here if users report them as necessary.
356  //
357  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
358  // the terminfo says that no colors are supported.
359  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
360 
361  // Now extract the structure allocated by setupterm and free its memory
362  // through a really silly dance.
363  struct term *termp = set_curterm(previous_term);
364  (void)del_curterm(termp); // Drop any errors here.
365 
366  // Return true if we found a color capabilities for the current terminal.
367  if (HasColors)
368  return true;
369 #else
370  // When the terminfo database is not available, check if the current terminal
371  // is one of terminals that are known to support ANSI color escape codes.
372  if (const char *TermStr = std::getenv("TERM")) {
373  return StringSwitch<bool>(TermStr)
374  .Case("ansi", true)
375  .Case("cygwin", true)
376  .Case("linux", true)
377  .StartsWith("screen", true)
378  .StartsWith("xterm", true)
379  .StartsWith("vt100", true)
380  .StartsWith("rxvt", true)
381  .EndsWith("color", true)
382  .Default(false);
383  }
384 #endif
385 
386  // Otherwise, be conservative.
387  return false;
388 }
389 
391  // A file descriptor has colors if it is displayed and the terminal has
392  // colors.
393  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
394 }
395 
397  return FileDescriptorHasColors(STDOUT_FILENO);
398 }
399 
401  return FileDescriptorHasColors(STDERR_FILENO);
402 }
403 
404 void Process::UseANSIEscapeCodes(bool /*enable*/) {
405  // No effect.
406 }
407 
409  // No, we use ANSI escape sequences.
410  return false;
411 }
412 
413 const char *Process::OutputColor(char code, bool bold, bool bg) {
414  return colorcodes[bg?1:0][bold?1:0][code&7];
415 }
416 
417 const char *Process::OutputBold(bool bg) {
418  return "\033[1m";
419 }
420 
421 const char *Process::OutputReverse() {
422  return "\033[7m";
423 }
424 
425 const char *Process::ResetColor() {
426  return "\033[0m";
427 }
428 
429 #if !HAVE_DECL_ARC4RANDOM
430 static unsigned GetRandomNumberSeed() {
431  // Attempt to get the initial seed from /dev/urandom, if possible.
432  int urandomFD = open("/dev/urandom", O_RDONLY);
433 
434  if (urandomFD != -1) {
435  unsigned seed;
436  // Don't use a buffered read to avoid reading more data
437  // from /dev/urandom than we need.
438  int count = read(urandomFD, (void *)&seed, sizeof(seed));
439 
440  close(urandomFD);
441 
442  // Return the seed if the read was successful.
443  if (count == sizeof(seed))
444  return seed;
445  }
446 
447  // Otherwise, swizzle the current time and the process ID to form a reasonable
448  // seed.
449  const auto Now = std::chrono::high_resolution_clock::now();
450  return hash_combine(Now.time_since_epoch().count(), ::getpid());
451 }
452 #endif
453 
455 #if HAVE_DECL_ARC4RANDOM
456  return arc4random();
457 #else
458  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
459  (void)x;
460  return ::rand();
461 #endif
462 }
463 
464 [[noreturn]] void Process::ExitNoCleanup(int RetCode) { _Exit(RetCode); }
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:67
i
i
Definition: README.txt:29
llvm::StringSwitch::StartsWith
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:81
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
zero
We currently generate a but we really shouldn eax ecx xorl edx divl ecx eax divl ecx movl eax ret A similar code sequence works for division We currently compile i32 v2 eax eax jo LBB1_2 atomic and others It is also currently not done for read modify write instructions It is also current not done if the OF or CF flags are needed The shift operators have the complication that when the shift count is zero
Definition: README.txt:1277
llvm::sys::Process::UseANSIEscapeCodes
static void UseANSIEscapeCodes(bool enable)
Enables or disables whether ANSI escape sequences are used to output colors.
StringRef.h
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
llvm::StringSwitch::EndsWith
StringSwitch & EndsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:74
llvm::sys::Process::StandardErrColumns
static unsigned StandardErrColumns()
This function determines the number of columns in the window if standard error is connected to a "tty...
ManagedStatic.h
llvm::sys::RetryAfterSignal
decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F, const Args &... As)
Definition: Errno.h:33
llvm::sys::Process::PreventCoreFiles
static void PreventCoreFiles()
This function makes the necessary calls to the operating system to prevent core files or any other ki...
llvm::Optional< std::string >
llvm::sys::Process::Pid
int32_t Pid
Definition: Process.h:46
Hashing.h
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
Unix.h
llvm::sys::Process::StandardOutHasColors
static bool StandardOutHasColors()
This function determines whether the terminal connected to standard output supports colors.
llvm::sys::Process::GetRandomNumber
static unsigned GetRandomNumber()
Get the result of a process wide random number generator.
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:90
llvm::ManagedStatic
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
false
Definition: StackSlotColoring.cpp:142
llvm::sys::Process::GetTimeUsage
static void GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, std::chrono::nanoseconds &sys_time)
This static function will set user_time to the amount of CPU time spent in user (non-kernel) mode and...
DebugLocVerifyLevel::None
@ None
colorcodes
static const char colorcodes[2][2][8][10]
Definition: Process.cpp:84
now
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
Definition: ArchiveWriter.cpp:259
llvm::sys::Process::OutputBold
static const char * OutputBold(bool bg)
Same as OutputColor, but only enables the bold attribute.
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::sys::Process::SafelyCloseFileDescriptor
static std::error_code SafelyCloseFileDescriptor(int FD)
llvm::sys::Process::FileDescriptorHasColors
static bool FileDescriptorHasColors(int fd)
This function determines if the given file descriptor is displayd and supports colors.
llvm::count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1664
llvm::sys::Process::ResetColor
static const char * ResetColor()
Resets the terminals colors, or returns an escape sequence to do so.
llvm::sys::Process::OutputColor
static const char * OutputColor(char c, bool bold, bool bg)
This function returns the colorcode escape sequences.
llvm::sys::Process::getPageSize
static Expected< unsigned > getPageSize()
Get the process's page size.
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::sys::Process::GetEnv
static Optional< std::string > GetEnv(StringRef name)
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::sys::Process::StandardErrHasColors
static bool StandardErrHasColors()
This function determines whether the terminal connected to standard error supports colors.
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::sys::Process::OutputReverse
static const char * OutputReverse()
This function returns the escape sequence to reverse forground and background colors.
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
Stats
block placement Basic Block Placement Stats
Definition: MachineBlockPlacement.cpp:3465
llvm::sys::Process::StandardOutIsDisplayed
static bool StandardOutIsDisplayed()
This function determines if the standard output is connected to a "tty" or "console" window.
code
*Add support for compiling functions in both ARM and Thumb then taking the smallest *Add support for compiling individual basic blocks in thumb when in a larger ARM function This can be used for presumed cold code
Definition: README-Thumb.txt:9
llvm::support::endian::read
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:63
llvm::sys::Process::StandardOutColumns
static unsigned StandardOutColumns()
This function determines the number of columns in the window if standard output is connected to a "tt...
llvm::sys::toDuration
std::chrono::nanoseconds toDuration(FILETIME Time)
Definition: WindowsSupport.h:201
x
TODO unsigned x
Definition: README.txt:10
llvm::sys::Process::FileDescriptorIsDisplayed
static bool FileDescriptorIsDisplayed(int fd)
This function determines if the given file descriptor is connected to a "tty" or "console" window.
llvm::sys::Process::ColorNeedsFlush
static bool ColorNeedsFlush()
Whether changing colors requires the output to be flushed.
llvm::sys::Process::getProcessId
static Pid getProcessId()
Get the process's identifier.
llvm::hash_combine
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:605
llvm::sys::Process::FixupStandardFileDescriptors
static std::error_code FixupStandardFileDescriptors()
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
coreFilesPrevented
static bool coreFilesPrevented
Definition: Process.cpp:91
llvm::sys::Process::GetMallocUsage
static size_t GetMallocUsage()
Return process memory usage.
llvm::sys::Process::StandardErrIsDisplayed
static bool StandardErrIsDisplayed()
This function determines if the standard error is connected to a "tty" or "console" window.
llvm::sys::Process::StandardInIsUserInput
static bool StandardInIsUserInput()
This function determines if the standard input is connected directly to a user's input (keyboard prob...