blob: 9d4a5aa7b1ce53419653b67de650e3d35a68ab28 [file] [log] [blame]
// Copyright 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/base/Debug.h"
#include "android/base/ArraySize.h"
#include "android/base/StringView.h"
#ifdef _WIN32
#include <windows.h>
#elif defined(__linux__)
#include <fstream>
#include <sstream>
#include <string>
#elif defined(__APPLE__)
#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>
#endif
namespace android {
namespace base {
#ifdef __linux__
static std::string readFile(StringView path) {
std::ifstream is(path.c_str());
if (!is) {
return {};
}
std::ostringstream ss;
ss << is.rdbuf();
return ss.str();
}
#endif
bool IsDebuggerAttached() {
#ifdef _WIN32
return ::IsDebuggerPresent() != 0;
#elif defined(__linux__)
std::string procStatus = readFile("/proc/self/status");
static constexpr StringView kTracerPidPrefix = "TracerPid:";
const auto tracerPid = procStatus.find(kTracerPidPrefix.data());
if (tracerPid == std::string::npos) {
return false;
}
// If the tracer PID is parseable and not 0, there's a debugger attached.
const bool debuggerAttached =
atoi(procStatus.c_str() + tracerPid + kTracerPidPrefix.size()) != 0;
return debuggerAttached;
#elif defined(__APPLE__)
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
struct kinfo_proc procInfo = {};
size_t infoSize;
const int res =
sysctl(mib, arraySize(mib), &procInfo, &infoSize, nullptr, 0);
if (res) {
return false;
}
return (procInfo.kp_proc.p_flag & P_TRACED) != 0;
#else
#error Unsupported platform
#endif
}
bool WaitForDebugger(System::Duration timeoutMs) {
static const System::Duration sleepTimeoutMs = 500;
System::Duration sleptForMs = 0;
while (!IsDebuggerAttached()
&& (timeoutMs == -1 || sleptForMs < timeoutMs)) {
System::get()->sleepMs(sleepTimeoutMs);
sleptForMs += sleepTimeoutMs;
}
return IsDebuggerAttached();
}
} // namespace base
} // namespace android