Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
break.cc
Go to the documentation of this file.
1 
18 #include "ion/port/break.h"
19 
20 #if defined(ION_PLATFORM_LINUX) || defined(ION_PLATFORM_ANDROID) || \
21  defined(ION_PLATFORM_GENERIC_ARM)
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #elif defined(ION_PLATFORM_MAC) || defined(ION_PLATFORM_IOS)
30 #include <assert.h>
31 #include <signal.h> // NOLINT
32 #include <stdbool.h>
33 #include <sys/sysctl.h>
34 #include <sys/types.h> // NOLINT
35 #include <unistd.h> // NOLINT
36 #elif defined(ION_PLATFORM_WINDOWS)
37 #include <intrin.h>
38 #include <windows.h>
39 #endif
40 
41 #include <cstdlib>
42 
43 namespace ion {
44 namespace port {
45 
46 #if defined(ION_PLATFORM_LINUX) || defined(ION_PLATFORM_ANDROID) || \
47  defined(ION_PLATFORM_GENERIC_ARM)
48 
49 bool IsDebuggerAttached() {
54  char buf[100];
55  int fd = open("/proc/self/status", O_RDONLY);
56  if (fd == -1) {
57  return false; // Can't tell for sure.
58  }
59  const ssize_t len = read(fd, buf, sizeof(buf));
60  bool rc = false;
61  if (len > 0) {
62  const char *const kTracerPid = "TracerPid:\t";
63  buf[len - 1] = '\0';
64  const char *p = strstr(buf, kTracerPid);
65  if (p != NULL) {
66  rc = (strncmp(p + strlen(kTracerPid), "0\n", 2) != 0);
67  }
68  }
69  close(fd);
70  return rc;
71 }
72 
73 #elif defined(ION_PLATFORM_MAC) || defined(ION_PLATFORM_IOS)
74 
75 bool IsDebuggerAttached() {
81  int junk;
82  int mib[4];
83  struct kinfo_proc info;
84  size_t size;
85 
88  info.kp_proc.p_flag = 0;
89 
92  mib[0] = CTL_KERN;
93  mib[1] = KERN_PROC;
94  mib[2] = KERN_PROC_PID;
95  mib[3] = getpid();
96 
98  size = sizeof(info);
99  junk = sysctl(
100  mib,
101  static_cast<u_int>(sizeof(mib) / sizeof(*mib)),
102  &info,
103  &size,
104  NULL,
105  0);
106  assert(junk == 0);
107 
109  return (info.kp_proc.p_flag & P_TRACED) != 0;
110 }
111 
112 #elif defined(ION_PLATFORM_WINDOWS)
113 
114 bool IsDebuggerAttached() {
115  return ::IsDebuggerPresent() ? true : false;
116 }
117 
118 #else
119 
122  return false;
123 }
124 
125 #endif
126 
127 void Break() {
128  if (IsDebuggerAttached()) {
129 #if defined(ION_PLATFORM_LINUX) || defined(ION_PLATFORM_ANDROID) || \
130  defined(ION_PLATFORM_MAC) || defined(ION_PLATFORM_IOS) || \
131  defined(ION_PLATFORM_GENERIC_ARM)
132  raise(SIGINT);
133 #elif defined(ION_PLATFORM_WINDOWS)
134  __debugbreak();
135 #else
136 #endif
138  }
139 }
140 
141 void BreakOrAbort() {
142  if (IsDebuggerAttached()) {
143  Break();
144  } else {
145  abort();
146  }
147 }
148 
149 } // namespace port
150 } // namespace ion
bool IsDebuggerAttached()
Don't break on unsupported platforms.
Definition: break.cc:121
void Break()
If a debugger is attached, this function interrupts the program execution and causes any attached deb...
Definition: break.cc:127
void BreakOrAbort()
Calls Break() if running in a debugger, abort() otherwise.
Definition: break.cc:141