[Lldb-commits] [lldb] b461398 - Add a new SBDebugger::SetDestroyCallback() API
Jeffrey Tan via lldb-commits
lldb-commits at lists.llvm.org
Tue Mar 7 14:48:34 PST 2023
Author: Jeffrey Tan
Date: 2023-03-07T14:48:15-08:00
New Revision: b461398f1ce307ec80708b7eb50f3bc82b76ed3f
URL: https://github.com/llvm/llvm-project/commit/b461398f1ce307ec80708b7eb50f3bc82b76ed3f
DIFF: https://github.com/llvm/llvm-project/commit/b461398f1ce307ec80708b7eb50f3bc82b76ed3f.diff
LOG: Add a new SBDebugger::SetDestroyCallback() API
Adding a new SBDebugger::SetDestroyCallback() API.
This API can be used by any client to query for statistics/metrics before
exiting debug sessions.
Differential Revision: https://reviews.llvm.org/D143520
Added:
Modified:
lldb/bindings/python/python-typemaps.swig
lldb/bindings/python/python-wrapper.swig
lldb/include/lldb/API/SBDebugger.h
lldb/include/lldb/API/SBDefines.h
lldb/include/lldb/Core/Debugger.h
lldb/include/lldb/lldb-private-types.h
lldb/source/API/SBDebugger.cpp
lldb/source/Core/Debugger.cpp
lldb/test/API/python_api/debugger/TestDebuggerAPI.py
Removed:
################################################################################
diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig
index 1b1f2e1fe2664..b3e7dd4ee265a 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -384,6 +384,29 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
}
+// For lldb::SBDebuggerDestroyCallback
+%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
+ if (!($input == Py_None ||
+ PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
+ PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
+ SWIG_fail;
+ }
+
+ // FIXME (filcab): We can't currently check if our callback is already
+ // LLDBSwigPythonCallPythonSBDebuggerTerminateCallback (to DECREF the previous
+ // baton) nor can we just remove all traces of a callback, if we want to
+ // revert to a file logging mechanism.
+
+ // Don't lose the callback reference
+ Py_INCREF($input);
+ $1 = LLDBSwigPythonCallPythonSBDebuggerTerminateCallback;
+ $2 = $input;
+}
+
+%typemap(typecheck) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
+ $1 = $input == Py_None;
+ $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
+}
%typemap(in) lldb::FileSP {
PythonFile py_file(PyRefType::Borrowed, $input);
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 26f79266538a5..d82c2dace18f3 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -1062,4 +1062,16 @@ static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str,
SWIG_PYTHON_THREAD_END_BLOCK;
}
}
+
+// For DebuggerTerminateCallback functions
+static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id,
+ void *baton) {
+ if (baton != Py_None) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyObject *result = PyObject_CallFunction(
+ reinterpret_cast<PyObject *>(baton), const_cast<char *>("l"), debugger_id);
+ Py_XDECREF(result);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+}
%}
diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h
index 80f76480363f3..8e8e1b61e08fb 100644
--- a/lldb/include/lldb/API/SBDebugger.h
+++ b/lldb/include/lldb/API/SBDebugger.h
@@ -316,6 +316,9 @@ class LLDB_API SBDebugger {
void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton);
+ void SetDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback,
+ void *baton);
+
// DEPRECATED
#ifndef SWIG
void DispatchInput(void *baton, const void *data, size_t data_len);
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index 848480d4f5e01..e7f8ca7b35f0d 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -110,6 +110,10 @@ class LLDB_API SBUnixSignals;
typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
SBThread &thread,
lldb::SBBreakpointLocation &location);
+
+typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
+ void *baton);
+
typedef void *ScriptedObject;
}
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 9f83a37bc75cc..07d9cf28beebf 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -450,6 +450,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
static void ReportSymbolChange(const ModuleSpec &module_spec);
+ void
+ SetDestroyCallback(lldb_private::DebuggerDestroyCallback destroy_callback,
+ void *baton);
+
protected:
friend class CommandInterpreter;
friend class REPL;
@@ -494,6 +498,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
std::optional<lldb::user_id_t> debugger_id,
std::once_flag *once);
+ void HandleDestroyCallback();
+
void PrintProgress(const ProgressEventData &data);
bool StartEventHandlerThread();
@@ -591,6 +597,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
llvm::once_flag m_clear_once;
lldb::TargetSP m_dummy_target_sp;
+ lldb_private::DebuggerDestroyCallback m_destroy_callback = nullptr;
+ void *m_destroy_callback_baton = nullptr;
+
// Events for m_sync_broadcaster
enum {
eBroadcastBitEventThreadIsListening = (1 << 0),
diff --git a/lldb/include/lldb/lldb-private-types.h b/lldb/include/lldb/lldb-private-types.h
index edc1c78985bdd..213e570667644 100644
--- a/lldb/include/lldb/lldb-private-types.h
+++ b/lldb/include/lldb/lldb-private-types.h
@@ -116,6 +116,8 @@ typedef struct type256 { uint64_t x[4]; } type256;
using ValueObjectProviderTy =
std::function<lldb::ValueObjectSP(ConstString, StackFrame *)>;
+typedef void (*DebuggerDestroyCallback)(lldb::user_id_t debugger_id,
+ void *baton);
} // namespace lldb_private
#endif // #if defined(__cplusplus)
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 641c84f0bd159..d90fcbf5031a4 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -1684,6 +1684,15 @@ void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
}
}
+void SBDebugger::SetDestroyCallback(
+ lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
+ LLDB_INSTRUMENT_VA(this, destroy_callback, baton);
+ if (m_opaque_sp) {
+ return m_opaque_sp->SetDestroyCallback(
+ destroy_callback, baton);
+ }
+}
+
SBTrace
SBDebugger::LoadTraceFromFile(SBError &error,
const SBFileSpec &trace_description_file) {
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 9c09da429d401..ae03ead2d654d 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -560,6 +560,12 @@ void Debugger::Terminate() {
assert(g_debugger_list_ptr &&
"Debugger::Terminate called without a matching Debugger::Initialize!");
+ if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
+ for (const auto &debugger : *g_debugger_list_ptr)
+ debugger->HandleDestroyCallback();
+ }
+
if (g_thread_pool) {
// The destructor will wait for all the threads to complete.
delete g_thread_pool;
@@ -679,10 +685,18 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
return debugger_sp;
}
+void Debugger::HandleDestroyCallback() {
+ if (m_destroy_callback) {
+ m_destroy_callback(GetID(), m_destroy_callback_baton);
+ m_destroy_callback = nullptr;
+ }
+}
+
void Debugger::Destroy(DebuggerSP &debugger_sp) {
if (!debugger_sp)
return;
+ debugger_sp->HandleDestroyCallback();
CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
if (cmd_interpreter.GetSaveSessionOnQuit()) {
@@ -1285,6 +1299,12 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
std::make_shared<CallbackLogHandler>(log_callback, baton);
}
+void Debugger::SetDestroyCallback(
+ lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
+ m_destroy_callback = destroy_callback;
+ m_destroy_callback_baton = baton;
+}
+
static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
std::string title, std::string details,
uint64_t completed, uint64_t total,
diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
index 6bc6b3bcbba81..dcc8e24774687 100644
--- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
+++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
@@ -30,7 +30,7 @@ def test_debugger_api_boundary_condition(self):
self.dbg.SetPrompt(None)
self.dbg.SetCurrentPlatform(None)
self.dbg.SetCurrentPlatformSDKRoot(None)
-
+
fresh_dbg = lldb.SBDebugger()
self.assertEquals(len(fresh_dbg), 0)
@@ -146,3 +146,16 @@ def test_CreateTarget_arch(self):
self.assertEqual(platform2.GetName(), expected_platform)
self.assertTrue(platform2.GetWorkingDirectory().endswith("bar"),
platform2.GetWorkingDirectory())
+
+ def test_SetDestroyCallback(self):
+ destroy_dbg_id = None
+ def foo(dbg_id):
+ # Need nonlocal to modify closure variable.
+ nonlocal destroy_dbg_id
+ destroy_dbg_id = dbg_id
+
+ self.dbg.SetDestroyCallback(foo)
+
+ original_dbg_id = self.dbg.GetID()
+ self.dbg.Destroy(self.dbg)
+ self.assertEqual(destroy_dbg_id, original_dbg_id)
More information about the lldb-commits
mailing list