Skip to content

Commit fecb53d

Browse files
Jeffrey Tanmedismailben
authored andcommitted
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
1 parent 18a1c81 commit fecb53d

File tree

8 files changed

+93
-0
lines changed

8 files changed

+93
-0
lines changed

lldb/bindings/python/python-typemaps.swig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,29 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
384384
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
385385
}
386386

387+
// For lldb::SBDebuggerDestroyCallback
388+
%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
389+
if (!($input == Py_None ||
390+
PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
391+
PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
392+
SWIG_fail;
393+
}
394+
395+
// FIXME (filcab): We can't currently check if our callback is already
396+
// LLDBSwigPythonCallPythonSBDebuggerTerminateCallback (to DECREF the previous
397+
// baton) nor can we just remove all traces of a callback, if we want to
398+
// revert to a file logging mechanism.
399+
400+
// Don't lose the callback reference
401+
Py_INCREF($input);
402+
$1 = LLDBSwigPythonCallPythonSBDebuggerTerminateCallback;
403+
$2 = $input;
404+
}
405+
406+
%typemap(typecheck) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
407+
$1 = $input == Py_None;
408+
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
409+
}
387410

388411
%typemap(in) lldb::FileSP {
389412
PythonFile py_file(PyRefType::Borrowed, $input);

lldb/bindings/python/python-wrapper.swig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,4 +1106,16 @@ static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str,
11061106
SWIG_PYTHON_THREAD_END_BLOCK;
11071107
}
11081108
}
1109+
1110+
// For DebuggerTerminateCallback functions
1111+
static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id,
1112+
void *baton) {
1113+
if (baton != Py_None) {
1114+
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
1115+
PyObject *result = PyObject_CallFunction(
1116+
reinterpret_cast<PyObject *>(baton), const_cast<char *>("l"), debugger_id);
1117+
Py_XDECREF(result);
1118+
SWIG_PYTHON_THREAD_END_BLOCK;
1119+
}
1120+
}
11091121
%}

lldb/include/lldb/API/SBDefines.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class LLDB_API SBUnixSignals;
122122
typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
123123
SBThread &thread,
124124
lldb::SBBreakpointLocation &location);
125+
126+
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
127+
void *baton);
128+
125129
typedef void *ScriptedObject;
126130
}
127131

lldb/include/lldb/Core/Debugger.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
479479

480480
static void ReportSymbolChange(const ModuleSpec &module_spec);
481481

482+
void
483+
SetDestroyCallback(lldb_private::DebuggerDestroyCallback destroy_callback,
484+
void *baton);
485+
482486
protected:
483487
friend class CommandInterpreter;
484488
friend class SwiftREPL;
@@ -524,6 +528,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
524528
llvm::Optional<lldb::user_id_t> debugger_id,
525529
std::once_flag *once);
526530

531+
void HandleDestroyCallback();
532+
527533
void PrintProgress(const ProgressEventData &data);
528534

529535
bool StartEventHandlerThread();
@@ -627,6 +633,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
627633
llvm::once_flag m_clear_once;
628634
lldb::TargetSP m_dummy_target_sp;
629635

636+
lldb_private::DebuggerDestroyCallback m_destroy_callback = nullptr;
637+
void *m_destroy_callback_baton = nullptr;
638+
630639
uint32_t m_interrupt_requested = 0; ///< Tracks interrupt requests
631640
std::mutex m_interrupt_mutex;
632641

lldb/include/lldb/lldb-private-types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ typedef struct type256 { uint64_t x[4]; } type256;
112112
using ValueObjectProviderTy =
113113
std::function<lldb::ValueObjectSP(ConstString, StackFrame *)>;
114114

115+
typedef void (*DebuggerDestroyCallback)(lldb::user_id_t debugger_id,
116+
void *baton);
115117
} // namespace lldb_private
116118

117119
#endif // #if defined(__cplusplus)

lldb/source/API/SBDebugger.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,15 @@ void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
16841684
}
16851685
}
16861686

1687+
void SBDebugger::SetDestroyCallback(
1688+
lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
1689+
LLDB_INSTRUMENT_VA(this, destroy_callback, baton);
1690+
if (m_opaque_sp) {
1691+
return m_opaque_sp->SetDestroyCallback(
1692+
destroy_callback, baton);
1693+
}
1694+
}
1695+
16871696
SBTrace
16881697
SBDebugger::LoadTraceFromFile(SBError &error,
16891698
const SBFileSpec &trace_description_file) {

lldb/source/Core/Debugger.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,12 @@ void Debugger::Terminate() {
559559
assert(g_debugger_list_ptr &&
560560
"Debugger::Terminate called without a matching Debugger::Initialize!");
561561

562+
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
563+
std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
564+
for (const auto &debugger : *g_debugger_list_ptr)
565+
debugger->HandleDestroyCallback();
566+
}
567+
562568
if (g_thread_pool) {
563569
// The destructor will wait for all the threads to complete.
564570
delete g_thread_pool;
@@ -678,10 +684,18 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
678684
return debugger_sp;
679685
}
680686

687+
void Debugger::HandleDestroyCallback() {
688+
if (m_destroy_callback) {
689+
m_destroy_callback(GetID(), m_destroy_callback_baton);
690+
m_destroy_callback = nullptr;
691+
}
692+
}
693+
681694
void Debugger::Destroy(DebuggerSP &debugger_sp) {
682695
if (!debugger_sp)
683696
return;
684697

698+
debugger_sp->HandleDestroyCallback();
685699
CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
686700

687701
if (cmd_interpreter.GetSaveSessionOnQuit()) {
@@ -1346,6 +1360,12 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
13461360
std::make_shared<CallbackLogHandler>(log_callback, baton);
13471361
}
13481362

1363+
void Debugger::SetDestroyCallback(
1364+
lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
1365+
m_destroy_callback = destroy_callback;
1366+
m_destroy_callback_baton = baton;
1367+
}
1368+
13491369
static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
13501370
std::string title, std::string details,
13511371
uint64_t completed, uint64_t total,

lldb/test/API/python_api/debugger/TestDebuggerAPI.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,17 @@ def test_CreateTarget_arch(self):
147147
platform2.GetWorkingDirectory().endswith("bar"),
148148
platform2.GetWorkingDirectory(),
149149
)
150+
151+
def test_SetDestroyCallback(self):
152+
destroy_dbg_id = None
153+
154+
def foo(dbg_id):
155+
# Need nonlocal to modify closure variable.
156+
nonlocal destroy_dbg_id
157+
destroy_dbg_id = dbg_id
158+
159+
self.dbg.SetDestroyCallback(foo)
160+
161+
original_dbg_id = self.dbg.GetID()
162+
self.dbg.Destroy(self.dbg)
163+
self.assertEqual(destroy_dbg_id, original_dbg_id)

0 commit comments

Comments
 (0)