sanitizer_posix.cc revision 859778a4e2dffa4024fa3e13b105fd62eca44b1c
11f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===-- sanitizer_posix.cc ------------------------------------------------===//
21f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//
31f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//                     The LLVM Compiler Infrastructure
41f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//
51f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// This file is distributed under the University of Illinois Open Source
61f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// License. See LICENSE.TXT for details.
71f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//
81f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===----------------------------------------------------------------------===//
91f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//
101f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
111f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// run-time libraries and implements POSIX-specific functions from
121f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov// sanitizer_libc.h.
131f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov//===----------------------------------------------------------------------===//
141f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#if defined(__linux__) || defined(__APPLE__)
151f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
16230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_common.h"
171f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include "sanitizer_libc.h"
18be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include "sanitizer_procmaps.h"
191f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
200aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany#include <errno.h>
21fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov#include <pthread.h>
221f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include <stdarg.h>
231f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#include <stdio.h>
24fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov#include <stdlib.h>
250aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany#include <string.h>
26230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <sys/mman.h>
27be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include <sys/resource.h>
28be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov#include <sys/time.h>
29230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <sys/types.h>
30230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include <unistd.h>
311f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
321f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovnamespace __sanitizer {
331f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
34be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov// ------------- sanitizer_common.h
35f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetPageSize() {
36f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return sysconf(_SC_PAGESIZE);
37f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany}
38f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany
39f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryanyuptr GetMmapGranularity() {
40f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return GetPageSize();
41f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany}
42be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
43230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovint GetPid() {
44230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return getpid();
45230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
46230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
47fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovuptr GetThreadSelf() {
48fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  return (uptr)pthread_self();
49fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
50fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
51a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonovvoid *MmapOrDie(uptr size, const char *mem_type) {
52f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  size = RoundUpTo(size, GetPageSizeCached());
53230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  void *res = internal_mmap(0, size,
54230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov                            PROT_READ | PROT_WRITE,
55230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov                            MAP_PRIVATE | MAP_ANON, -1, 0);
56230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  if (res == (void*)-1) {
57e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany    static int recursion_count;
58e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany    if (recursion_count) {
59e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany      // The Report() and CHECK calls below may call mmap recursively and fail.
60e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany      // If we went into recursion, just die.
61c8490e2a09cd415cc58fc8f3b63bebddce61c82dDmitry Vyukov      RawWrite("ERROR: Failed to mmap\n");
62e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany      Die();
63e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany    }
64e8216fd93f6f8980965197a1779b6f54441255caKostya Serebryany    recursion_count++;
65859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany    Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
66859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           SanitizerToolName, size, size, mem_type, strerror(errno));
670aa04b3f432bc55e7c116d5280685ee3f243be8eKostya Serebryany    DumpProcessMap();
68a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov    CHECK("unable to mmap" && 0);
69230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  }
70230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return res;
71230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
72230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
73230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovvoid UnmapOrDie(void *addr, uptr size) {
74230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  if (!addr || !size) return;
75230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  int res = internal_munmap(addr, size);
76230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  if (res != 0) {
77859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany    Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
78859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           SanitizerToolName, size, size, addr);
79a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov    CHECK("unable to unmap" && 0);
80230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  }
81230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
82230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
83f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonovvoid *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
84f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr PageSize = GetPageSizeCached();
85f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
86f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany      RoundUpTo(size, PageSize),
876b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov      PROT_READ | PROT_WRITE,
886b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
896b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov      -1, 0);
906b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov  if (p == (void*)-1)
91859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany    Report("ERROR: "
92859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
93859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           SanitizerToolName, size, size, fixed_addr, errno);
94785a7c07c9bd2d4463b30a8539a716f020139551Dmitry Vyukov  return p;
95f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov}
96f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov
979bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryanyvoid *MmapFixedOrDie(uptr fixed_addr, uptr size) {
989bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  uptr PageSize = GetPageSizeCached();
999bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
1009bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany      RoundUpTo(size, PageSize),
1019bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany      PROT_READ | PROT_WRITE,
1029bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany      MAP_PRIVATE | MAP_ANON | MAP_FIXED,
1039bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany      -1, 0);
1049bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  if (p == (void*)-1) {
105859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany    Report("ERROR:"
106859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
107859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany           SanitizerToolName, size, size, fixed_addr, errno);
1089bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany    CHECK("unable to mmap" && 0);
1099bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  }
1109bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany  return p;
1119bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany}
1129bfe78f7d4f9af3cdacb4d34bd7b4fead27dcda5Kostya Serebryany
113f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonovvoid *Mprotect(uptr fixed_addr, uptr size) {
114f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov  return internal_mmap((void*)fixed_addr, size,
115f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov                       PROT_NONE,
116f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov                       MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
11784902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov                       -1, 0);
118f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov}
119f607fc1c67a613a59a1db3c80c5d1322e1978102Alexey Samsonov
120a54aec8ca2e372b1a841d605d53cab5e336aeb03Kostya Serebryanyvoid FlushUnneededShadowMemory(uptr addr, uptr size) {
121a54aec8ca2e372b1a841d605d53cab5e336aeb03Kostya Serebryany  madvise((void*)addr, size, MADV_DONTNEED);
122a54aec8ca2e372b1a841d605d53cab5e336aeb03Kostya Serebryany}
123a54aec8ca2e372b1a841d605d53cab5e336aeb03Kostya Serebryany
124a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonovvoid *MapFileToMemory(const char *file_name, uptr *buff_size) {
125a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  fd_t fd = internal_open(file_name, false);
126a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  CHECK_NE(fd, kInvalidFd);
127a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  uptr fsize = internal_filesize(fd);
128a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  CHECK_NE(fsize, (uptr)-1);
129a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  CHECK_GT(fsize, 0);
130f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  *buff_size = RoundUpTo(fsize, GetPageSizeCached());
131a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
132a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  return (map == MAP_FAILED) ? 0 : map;
133a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov}
134a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov
135a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov
136dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovstatic inline bool IntervalsAreSeparate(uptr start1, uptr end1,
137dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov                                        uptr start2, uptr end2) {
138dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  CHECK(start1 <= end1);
139dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  CHECK(start2 <= end2);
140dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  return (end1 < start2) || (end2 < start1);
141dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov}
142dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov
143dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// FIXME: this is thread-unsafe, but should not cause problems most of the time.
144dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// When the shadow is mapped only a single thread usually exists (plus maybe
145dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// several worker threads on Mac, which aren't expected to map big chunks of
146dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov// memory).
147dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonovbool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
148e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  MemoryMappingLayout procmaps;
149dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  uptr start, end;
150dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  while (procmaps.Next(&start, &end,
151dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov                       /*offset*/0, /*filename*/0, /*filename_size*/0)) {
152dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov    if (!IntervalsAreSeparate(start, end, range_start, range_end))
153dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov      return false;
154dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  }
155dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov  return true;
156dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov}
157dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov
158be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonovvoid DumpProcessMap() {
159e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  MemoryMappingLayout proc_maps;
160be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  uptr start, end;
161be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  const sptr kBufSize = 4095;
162b84ee029ada36949c30c57c5f701191783990574Alexey Samsonov  char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
163be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  Report("Process memory map follows:\n");
164be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  while (proc_maps.Next(&start, &end, /* file_offset */0,
165be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov                        filename, kBufSize)) {
166be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov    Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename);
167be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  }
168be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  Report("End of process memory map.\n");
169b84ee029ada36949c30c57c5f701191783990574Alexey Samsonov  UnmapOrDie(filename, kBufSize);
170be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov}
171be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
1720969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovconst char *GetPwd() {
1730969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  return GetEnv("PWD");
1740969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
1750969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
176be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonovvoid DisableCoreDumper() {
177be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  struct rlimit nocore;
178be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  nocore.rlim_cur = 0;
179be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  nocore.rlim_max = 0;
180be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov  setrlimit(RLIMIT_CORE, &nocore);
181be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov}
182be7420cc79d8580eb354666eef638d39ee9cff80Alexey Samsonov
183d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovbool StackSizeIsUnlimited() {
184d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  struct rlimit rlim;
185d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
186d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  return (rlim.rlim_cur == (uptr)-1);
187d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
188d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
189d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid SetStackSizeLimitInBytes(uptr limit) {
190d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  struct rlimit rlim;
191d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  rlim.rlim_cur = limit;
192d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  rlim.rlim_max = limit;
193d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  if (setrlimit(RLIMIT_STACK, &rlim)) {
194859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany    Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
195d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov    Die();
196d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  }
197d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  CHECK(!StackSizeIsUnlimited());
198d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
199d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
200fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid SleepForSeconds(int seconds) {
201fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  sleep(seconds);
202fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
203fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
2040969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovvoid SleepForMillis(int millis) {
2050969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  usleep(millis * 1000);
2060969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
2070969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
208fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid Exit(int exitcode) {
209fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  _exit(exitcode);
210fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
211fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
212fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovvoid Abort() {
213fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  abort();
214fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
215fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
216fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonovint Atexit(void (*function)(void)) {
217b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef SANITIZER_GO
218fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov  return atexit(function);
219b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
220b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return 0;
221b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
222fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov}
223fa3daaf1d66314658e7c05bf63dc825d179f2fafAlexey Samsonov
22484d57b4ce545d6c19effac01124749a9df0fd0a5Alexey Samsonovint internal_isatty(fd_t fd) {
22584d57b4ce545d6c19effac01124749a9df0fd0a5Alexey Samsonov  return isatty(fd);
22684d57b4ce545d6c19effac01124749a9df0fd0a5Alexey Samsonov}
22784d57b4ce545d6c19effac01124749a9df0fd0a5Alexey Samsonov
2281f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}  // namespace __sanitizer
2291f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
2301f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov#endif  // __linux__ || __APPLE_
231