--- /dev/null
+#ifndef _WIN32
+#include <signal.h>
+#endif
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "debugapi.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Debug {
+
+DebuggerType check_debugger(bool force_recheck)
+{
+ static DebuggerType debugger = NONE;
+ static bool checked = false;
+
+ if(!checked || force_recheck)
+ {
+ checked = true;
+
+#ifndef _WIN32
+ unsigned tracer_pid = 0;
+ IO::BufferedFile status("/proc/self/status");
+ string line;
+ while(status.getline(line))
+ if(!line.compare(0, 10, "TracerPid:"))
+ {
+ tracer_pid = lexical_cast<unsigned>(strip(line.substr(10)));
+ break;
+ }
+
+ if(tracer_pid)
+ {
+ FS::Path tracer_cmd = FS::readlink(format("/proc/%d/exe", tracer_pid));
+ if(FS::basename(tracer_cmd)=="gdb")
+ debugger = GDB;
+ else
+ debugger = UNKNOWN;
+ }
+#endif
+ }
+
+ return debugger;
+}
+
+void debug_break()
+{
+#ifdef _WIN32
+ __debugbreak();
+#else
+ raise(SIGTRAP);
+#endif
+}
+
+} // namespace Debug
+} // namespace Msp
--- /dev/null
+#ifndef MSP_DEBUG_DEBUGAPI_H_
+#define MSP_DEBUG_DEBUGAPI_H_
+
+namespace Msp {
+namespace Debug {
+
+enum DebuggerType
+{
+ NONE,
+ GDB,
+ UNKNOWN,
+};
+
+DebuggerType check_debugger(bool = false);
+void debug_break();
+
+} // namespace Debug
+} // namespace Msp
+
+#endif