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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits