Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Support/Unix/Process.inc
Line
Count
Source (jump to first uncovered line)
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"
17
#include "llvm/Support/ManagedStatic.h"
18
#include "llvm/Support/Mutex.h"
19
#include "llvm/Support/MutexGuard.h"
20
#if HAVE_FCNTL_H
21
#include <fcntl.h>
22
#endif
23
#ifdef HAVE_SYS_TIME_H
24
#include <sys/time.h>
25
#endif
26
#ifdef HAVE_SYS_RESOURCE_H
27
#include <sys/resource.h>
28
#endif
29
#ifdef HAVE_SYS_STAT_H
30
#include <sys/stat.h>
31
#endif
32
#if HAVE_SIGNAL_H
33
#include <signal.h>
34
#endif
35
#if defined(HAVE_MALLINFO)
36
#include <malloc.h>
37
#endif
38
#if defined(HAVE_MALLCTL)
39
#include <malloc_np.h>
40
#endif
41
#ifdef HAVE_MALLOC_MALLOC_H
42
#include <malloc/malloc.h>
43
#endif
44
#ifdef HAVE_SYS_IOCTL_H
45
#  include <sys/ioctl.h>
46
#endif
47
#ifdef HAVE_TERMIOS_H
48
#  include <termios.h>
49
#endif
50
51
//===----------------------------------------------------------------------===//
52
//=== WARNING: Implementation here must contain only generic UNIX code that
53
//===          is guaranteed to work on *all* UNIX variants.
54
//===----------------------------------------------------------------------===//
55
56
using namespace llvm;
57
using namespace sys;
58
59
10.8k
static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
60
10.8k
#if defined(HAVE_GETRUSAGE)
61
10.8k
  struct rusage RU;
62
10.8k
  ::getrusage(RUSAGE_SELF, &RU);
63
10.8k
  return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
64
#else
65
#warning Cannot get usage times on this platform
66
  return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() };
67
#endif
68
}
69
70
// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
71
// offset in mmap(3) should be aligned to the AllocationGranularity.
72
288k
Expected<unsigned> Process::getPageSize() {
73
288k
#if defined(HAVE_GETPAGESIZE)
74
288k
  static const int page_size = ::getpagesize();
75
#elif defined(HAVE_SYSCONF)
76
  static long page_size = ::sysconf(_SC_PAGE_SIZE);
77
#else
78
#error Cannot get the page size on this machine
79
#endif
80
288k
  if (page_size == -1)
81
0
    return errorCodeToError(std::error_code(errno, std::generic_category()));
82
288k
83
288k
  return static_cast<unsigned>(page_size);
84
288k
}
85
86
0
size_t Process::GetMallocUsage() {
87
#if defined(HAVE_MALLINFO)
88
  struct mallinfo mi;
89
  mi = ::mallinfo();
90
  return mi.uordblks;
91
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
92
  malloc_statistics_t Stats;
93
0
  malloc_zone_statistics(malloc_default_zone(), &Stats);
94
0
  return Stats.size_in_use;   // darwin
95
#elif defined(HAVE_MALLCTL)
96
  size_t alloc, sz;
97
  sz = sizeof(size_t);
98
  if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
99
    return alloc;
100
  return 0;
101
#elif defined(HAVE_SBRK)
102
  // Note this is only an approximation and more closely resembles
103
  // the value returned by mallinfo in the arena field.
104
  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
105
  char *EndOfMemory = (char*)sbrk(0);
106
  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
107
    return EndOfMemory - StartOfMemory;
108
  return 0;
109
#else
110
#warning Cannot get malloc info on this platform
111
  return 0;
112
#endif
113
}
114
115
void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
116
10.8k
                           std::chrono::nanoseconds &sys_time) {
117
10.8k
  elapsed = std::chrono::system_clock::now();
118
10.8k
  std::tie(user_time, sys_time) = getRUsageTimes();
119
10.8k
}
120
121
#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
122
#include <mach/mach.h>
123
#endif
124
125
// Some LLVM programs such as bugpoint produce core files as a normal part of
126
// their operation. To prevent the disk from filling up, this function
127
// does what's necessary to prevent their generation.
128
13
void Process::PreventCoreFiles() {
129
13
#if HAVE_SETRLIMIT
130
13
  struct rlimit rlim;
131
13
  rlim.rlim_cur = rlim.rlim_max = 0;
132
13
  setrlimit(RLIMIT_CORE, &rlim);
133
13
#endif
134
13
135
13
#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
136
13
  // Disable crash reporting on Mac OS X 10.0-10.4
137
13
138
13
  // get information about the original set of exception ports for the task
139
13
  mach_msg_type_number_t Count = 0;
140
13
  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
141
13
  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
142
13
  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
143
13
  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
144
13
  kern_return_t err =
145
13
    task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
146
13
                             &Count, OriginalPorts, OriginalBehaviors,
147
13
                             OriginalFlavors);
148
13
  if (err == KERN_SUCCESS) {
149
13
    // replace each with MACH_PORT_NULL.
150
39
    for (unsigned i = 0; i != Count; 
++i26
)
151
26
      task_set_exception_ports(mach_task_self(), OriginalMasks[i],
152
26
                               MACH_PORT_NULL, OriginalBehaviors[i],
153
26
                               OriginalFlavors[i]);
154
13
  }
155
13
156
13
  // Disable crash reporting on Mac OS X 10.5
157
13
  signal(SIGABRT, _exit);
158
13
  signal(SIGILL,  _exit);
159
13
  signal(SIGFPE,  _exit);
160
13
  signal(SIGSEGV, _exit);
161
13
  signal(SIGBUS,  _exit);
162
13
#endif
163
13
164
13
  coreFilesPrevented = true;
165
13
}
166
167
36.3k
Optional<std::string> Process::GetEnv(StringRef Name) {
168
36.3k
  std::string NameStr = Name.str();
169
36.3k
  const char *Val = ::getenv(NameStr.c_str());
170
36.3k
  if (!Val)
171
35.6k
    return None;
172
659
  return std::string(Val);
173
659
}
174
175
namespace {
176
class FDCloser {
177
public:
178
60.0k
  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
179
0
  void keepOpen() { KeepOpen = true; }
180
60.0k
  ~FDCloser() {
181
60.0k
    if (!KeepOpen && FD >= 0)
182
0
      ::close(FD);
183
60.0k
  }
184
185
private:
186
  FDCloser(const FDCloser &) = delete;
187
  void operator=(const FDCloser &) = delete;
188
189
  int &FD;
190
  bool KeepOpen;
191
};
192
}
193
194
60.0k
std::error_code Process::FixupStandardFileDescriptors() {
195
60.0k
  int NullFD = -1;
196
60.0k
  FDCloser FDC(NullFD);
197
60.0k
  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
198
180k
  for (int StandardFD : StandardFDs) {
199
180k
    struct stat st;
200
180k
    errno = 0;
201
180k
    if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
202
0
      assert(errno && "expected errno to be set if fstat failed!");
203
0
      // fstat should return EBADF if the file descriptor is closed.
204
0
      if (errno != EBADF)
205
0
        return std::error_code(errno, std::generic_category());
206
180k
    }
207
180k
    // if fstat succeeds, move on to the next FD.
208
180k
    if (!errno)
209
180k
      continue;
210
0
    assert(errno == EBADF && "expected errno to have EBADF at this point!");
211
0
212
0
    if (NullFD < 0) {
213
0
      // Call ::open in a lambda to avoid overload resolution in
214
0
      // RetryAfterSignal when open is overloaded, such as in Bionic.
215
0
      auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
216
0
      if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
217
0
        return std::error_code(errno, std::generic_category());
218
0
    }
219
0
220
0
    if (NullFD == StandardFD)
221
0
      FDC.keepOpen();
222
0
    else if (dup2(NullFD, StandardFD) < 0)
223
0
      return std::error_code(errno, std::generic_category());
224
0
  }
225
60.0k
  return std::error_code();
226
60.0k
}
227
228
599k
std::error_code Process::SafelyCloseFileDescriptor(int FD) {
229
599k
  // Create a signal set filled with *all* signals.
230
599k
  sigset_t FullSet;
231
599k
  if (sigfillset(&FullSet) < 0)
232
0
    return std::error_code(errno, std::generic_category());
233
599k
  // Atomically swap our current signal mask with a full mask.
234
599k
  sigset_t SavedSet;
235
599k
#if LLVM_ENABLE_THREADS
236
599k
  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
237
0
    return std::error_code(EC, std::generic_category());
238
#else
239
  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
240
    return std::error_code(errno, std::generic_category());
241
#endif
242
  // Attempt to close the file descriptor.
243
599k
  // We need to save the error, if one occurs, because our subsequent call to
244
599k
  // pthread_sigmask might tamper with errno.
245
599k
  int ErrnoFromClose = 0;
246
599k
  if (::close(FD) < 0)
247
0
    ErrnoFromClose = errno;
248
599k
  // Restore the signal mask back to what we saved earlier.
249
599k
  int EC = 0;
250
599k
#if LLVM_ENABLE_THREADS
251
599k
  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
252
#else
253
  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
254
    EC = errno;
255
#endif
256
  // The error code from close takes precedence over the one from
257
599k
  // pthread_sigmask.
258
599k
  if (ErrnoFromClose)
259
0
    return std::error_code(ErrnoFromClose, std::generic_category());
260
599k
  return std::error_code(EC, std::generic_category());
261
599k
}
262
263
1.24k
bool Process::StandardInIsUserInput() {
264
1.24k
  return FileDescriptorIsDisplayed(STDIN_FILENO);
265
1.24k
}
266
267
0
bool Process::StandardOutIsDisplayed() {
268
0
  return FileDescriptorIsDisplayed(STDOUT_FILENO);
269
0
}
270
271
29.5k
bool Process::StandardErrIsDisplayed() {
272
29.5k
  return FileDescriptorIsDisplayed(STDERR_FILENO);
273
29.5k
}
274
275
987k
bool Process::FileDescriptorIsDisplayed(int fd) {
276
987k
#if HAVE_ISATTY
277
987k
  return isatty(fd);
278
#else
279
  // If we don't have isatty, just return false.
280
  return false;
281
#endif
282
}
283
284
0
static unsigned getColumns(int FileID) {
285
0
  // If COLUMNS is defined in the environment, wrap to that many columns.
286
0
  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
287
0
    int Columns = std::atoi(ColumnsStr);
288
0
    if (Columns > 0)
289
0
      return Columns;
290
0
  }
291
0
292
0
  unsigned Columns = 0;
293
0
294
0
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) \
295
0
  && !(defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE))
296
0
  // Try to determine the width of the terminal.
297
0
  struct winsize ws;
298
0
  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
299
0
    Columns = ws.ws_col;
300
0
#endif
301
0
302
0
  return Columns;
303
0
}
304
305
0
unsigned Process::StandardOutColumns() {
306
0
  if (!StandardOutIsDisplayed())
307
0
    return 0;
308
0
309
0
  return getColumns(1);
310
0
}
311
312
29.5k
unsigned Process::StandardErrColumns() {
313
29.5k
  if (!StandardErrIsDisplayed())
314
29.5k
    return 0;
315
0
316
0
  return getColumns(2);
317
0
}
318
319
#ifdef HAVE_TERMINFO
320
// We manually declare these extern functions because finding the correct
321
// headers from various terminfo, curses, or other sources is harder than
322
// writing their specs down.
323
extern "C" int setupterm(char *term, int filedes, int *errret);
324
extern "C" struct term *set_curterm(struct term *termp);
325
extern "C" int del_curterm(struct term *termp);
326
extern "C" int tigetnum(char *capname);
327
#endif
328
329
#ifdef HAVE_TERMINFO
330
static ManagedStatic<sys::Mutex> TermColorMutex;
331
#endif
332
333
0
static bool terminalHasColors(int fd) {
334
0
#ifdef HAVE_TERMINFO
335
0
  // First, acquire a global lock because these C routines are thread hostile.
336
0
  MutexGuard G(*TermColorMutex);
337
0
338
0
  int errret = 0;
339
0
  if (setupterm(nullptr, fd, &errret) != 0)
340
0
    // Regardless of why, if we can't get terminfo, we shouldn't try to print
341
0
    // colors.
342
0
    return false;
343
0
344
0
  // Test whether the terminal as set up supports color output. How to do this
345
0
  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
346
0
  // would be nice to avoid a dependency on curses proper when we can make do
347
0
  // with a minimal terminfo parsing library. Also, we don't really care whether
348
0
  // the terminal supports the curses-specific color changing routines, merely
349
0
  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
350
0
  // strategy here is just to query the baseline colors capability and if it
351
0
  // supports colors at all to assume it will translate the escape codes into
352
0
  // whatever range of colors it does support. We can add more detailed tests
353
0
  // here if users report them as necessary.
354
0
  //
355
0
  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
356
0
  // the terminfo says that no colors are supported.
357
0
  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
358
0
359
0
  // Now extract the structure allocated by setupterm and free its memory
360
0
  // through a really silly dance.
361
0
  struct term *termp = set_curterm(nullptr);
362
0
  (void)del_curterm(termp); // Drop any errors here.
363
0
364
0
  // Return true if we found a color capabilities for the current terminal.
365
0
  if (HasColors)
366
0
    return true;
367
#else
368
  // When the terminfo database is not available, check if the current terminal
369
  // is one of terminals that are known to support ANSI color escape codes.
370
  if (const char *TermStr = std::getenv("TERM")) {
371
    return StringSwitch<bool>(TermStr)
372
      .Case("ansi", true)
373
      .Case("cygwin", true)
374
      .Case("linux", true)
375
      .StartsWith("screen", true)
376
      .StartsWith("xterm", true)
377
      .StartsWith("vt100", true)
378
      .StartsWith("rxvt", true)
379
      .EndsWith("color", true)
380
      .Default(false);
381
  }
382
#endif
383
384
0
  // Otherwise, be conservative.
385
0
  return false;
386
0
}
387
388
948k
bool Process::FileDescriptorHasColors(int fd) {
389
948k
  // A file descriptor has colors if it is displayed and the terminal has
390
948k
  // colors.
391
948k
  return FileDescriptorIsDisplayed(fd) && 
terminalHasColors(fd)0
;
392
948k
}
393
394
263
bool Process::StandardOutHasColors() {
395
263
  return FileDescriptorHasColors(STDOUT_FILENO);
396
263
}
397
398
29.7k
bool Process::StandardErrHasColors() {
399
29.7k
  return FileDescriptorHasColors(STDERR_FILENO);
400
29.7k
}
401
402
74.5k
void Process::UseANSIEscapeCodes(bool /*enable*/) {
403
74.5k
  // No effect.
404
74.5k
}
405
406
1.58k
bool Process::ColorNeedsFlush() {
407
1.58k
  // No, we use ANSI escape sequences.
408
1.58k
  return false;
409
1.58k
}
410
411
686
const char *Process::OutputColor(char code, bool bold, bool bg) {
412
686
  return colorcodes[bg?
10
:0][bold?
1269
:
0417
][code&7];
413
686
}
414
415
110
const char *Process::OutputBold(bool bg) {
416
110
  return "\033[1m";
417
110
}
418
419
0
const char *Process::OutputReverse() {
420
0
  return "\033[7m";
421
0
}
422
423
789
const char *Process::ResetColor() {
424
789
  return "\033[0m";
425
789
}
426
427
#if !HAVE_DECL_ARC4RANDOM
428
static unsigned GetRandomNumberSeed() {
429
  // Attempt to get the initial seed from /dev/urandom, if possible.
430
  int urandomFD = open("/dev/urandom", O_RDONLY);
431
432
  if (urandomFD != -1) {
433
    unsigned seed;
434
    // Don't use a buffered read to avoid reading more data
435
    // from /dev/urandom than we need.
436
    int count = read(urandomFD, (void *)&seed, sizeof(seed));
437
438
    close(urandomFD);
439
440
    // Return the seed if the read was successful.
441
    if (count == sizeof(seed))
442
      return seed;
443
  }
444
445
  // Otherwise, swizzle the current time and the process ID to form a reasonable
446
  // seed.
447
  const auto Now = std::chrono::high_resolution_clock::now();
448
  return hash_combine(Now.time_since_epoch().count(), ::getpid());
449
}
450
#endif
451
452
275k
unsigned llvm::sys::Process::GetRandomNumber() {
453
275k
#if HAVE_DECL_ARC4RANDOM
454
275k
  return arc4random();
455
#else
456
  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
457
  (void)x;
458
  return ::rand();
459
#endif
460
}