Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_debugger.cpp
Go to the documentation of this file.
1/*
2 * Created by Phil on 27/12/2010.
3 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4 *
5 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 *
8 */
9
10#include "catch_debugger.h"
11#include "catch_errno_guard.h"
12#include "catch_stream.h"
13#include "catch_platform.h"
14
15#ifdef CATCH_PLATFORM_MAC
16
17# include <assert.h>
18# include <stdbool.h>
19# include <sys/types.h>
20# include <unistd.h>
21# include <cstddef>
22# include <ostream>
23
24#ifdef __apple_build_version__
25 // These headers will only compile with AppleClang (XCode)
26 // For other compilers (Clang, GCC, ... ) we need to exclude them
27# include <sys/sysctl.h>
28#endif
29
30 namespace Catch {
31 #ifdef __apple_build_version__
32 // The following function is taken directly from the following technical note:
33 // https://developer.apple.com/library/archive/qa/qa1361/_index.html
34
35 // Returns true if the current process is being debugged (either
36 // running under the debugger or has a debugger attached post facto).
37 bool isDebuggerActive(){
38 int mib[4];
39 struct kinfo_proc info;
40 std::size_t size;
41
42 // Initialize the flags so that, if sysctl fails for some bizarre
43 // reason, we get a predictable result.
44
45 info.kp_proc.p_flag = 0;
46
47 // Initialize mib, which tells sysctl the info we want, in this case
48 // we're looking for information about a specific process ID.
49
50 mib[0] = CTL_KERN;
51 mib[1] = KERN_PROC;
52 mib[2] = KERN_PROC_PID;
53 mib[3] = getpid();
54
55 // Call sysctl.
56
57 size = sizeof(info);
58 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
59 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
60 return false;
61 }
62
63 // We're being debugged if the P_TRACED flag is set.
64
65 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
66 }
67 #else
68 bool isDebuggerActive() {
69 // We need to find another way to determine this for non-appleclang compilers on macOS
70 return false;
71 }
72 #endif
73 } // namespace Catch
74
75#elif defined(CATCH_PLATFORM_LINUX)
76 #include <fstream>
77 #include <string>
78
79 namespace Catch{
80 // The standard POSIX way of detecting a debugger is to attempt to
81 // ptrace() the process, but this needs to be done from a child and not
82 // this process itself to still allow attaching to this process later
83 // if wanted, so is rather heavy. Under Linux we have the PID of the
84 // "debugger" (which doesn't need to be gdb, of course, it could also
85 // be strace, for example) in /proc/$PID/status, so just get it from
86 // there instead.
87 bool isDebuggerActive(){
88 // Libstdc++ has a bug, where std::ifstream sets errno to 0
89 // This way our users can properly assert over errno values
90 ErrnoGuard guard;
91 std::ifstream in("/proc/self/status");
92 for( std::string line; std::getline(in, line); ) {
93 static const int PREFIX_LEN = 11;
94 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
95 // We're traced if the PID is not 0 and no other PID starts
96 // with 0 digit, so it's enough to check for just a single
97 // character.
98 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
99 }
100 }
101
102 return false;
103 }
104 } // namespace Catch
105#elif defined(_MSC_VER)
106 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
107 namespace Catch {
108 bool isDebuggerActive() {
109 return IsDebuggerPresent() != 0;
110 }
111 }
112#elif defined(__MINGW32__)
113 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
114 namespace Catch {
115 bool isDebuggerActive() {
116 return IsDebuggerPresent() != 0;
117 }
118 }
119#else
120 namespace Catch {
121 bool isDebuggerActive() { return false; }
122 }
123#endif // Platform
std::ostream & cerr()
bool isDebuggerActive()