gdb/python: add a new gdb_exiting event
Add a new event, gdb.events.gdb_exiting, which is called once GDB decides it is going to exit. This event is not triggered in the case that GDB performs a hard abort, for example, when handling an internal error and the user decides to quit the debug session, or if GDB hits an unexpected, fatal, signal. This event is triggered if the user just types 'quit' at the command prompt, or if GDB is run with '-batch' and has processed all of the required commands. The new event type is gdb.GdbExitingEvent, and it has a single attribute exit_code, which is the value that GDB is about to exit with. The event is triggered before GDB starts dismantling any of its own internal state, so, my expectation is that most Python calls should work just fine at this point. When considering this functionality I wondered about using the 'atexit' Python module. However, this is triggered when the Python environment is shut down, which is done from a final cleanup. At this point we don't know for sure what other GDB state has already been cleaned up.
This commit is contained in:
parent
1cb56ad3f3
commit
b1f0f28418
10 changed files with 141 additions and 5 deletions
|
@ -36,6 +36,7 @@
|
|||
#include "location.h"
|
||||
#include "run-on-main-thread.h"
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "observable.h"
|
||||
|
||||
/* Declared constants and enum for python stack printing. */
|
||||
static const char python_excp_none[] = "none";
|
||||
|
@ -1720,6 +1721,38 @@ init__gdb_module (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Emit a gdb.GdbExitingEvent, return a negative value if there are any
|
||||
errors, otherwise, return 0. */
|
||||
|
||||
static int
|
||||
emit_exiting_event (int exit_code)
|
||||
{
|
||||
gdbpy_ref<> event_obj = create_event_object (&gdb_exiting_event_object_type);
|
||||
if (event_obj == nullptr)
|
||||
return -1;
|
||||
|
||||
gdbpy_ref<> code = gdb_py_object_from_longest (exit_code);
|
||||
if (evpy_add_attribute (event_obj.get (), "exit_code", code.get ()) < 0)
|
||||
return -1;
|
||||
|
||||
return evpy_emit_event (event_obj.get (), gdb_py_events.gdb_exiting);
|
||||
}
|
||||
|
||||
/* Callback for the gdb_exiting observable. EXIT_CODE is the value GDB
|
||||
will exit with. */
|
||||
|
||||
static void
|
||||
gdbpy_gdb_exiting (int exit_code)
|
||||
{
|
||||
if (!gdb_python_initialized)
|
||||
return;
|
||||
|
||||
gdbpy_enter enter_py (python_gdbarch, python_language);
|
||||
|
||||
if (emit_exiting_event (exit_code) < 0)
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
|
||||
static bool
|
||||
do_start_initialization ()
|
||||
{
|
||||
|
@ -1871,6 +1904,8 @@ do_start_initialization ()
|
|||
if (gdbpy_value_cst == NULL)
|
||||
return false;
|
||||
|
||||
gdb::observers::gdb_exiting.attach (gdbpy_gdb_exiting, "python");
|
||||
|
||||
/* Release the GIL while gdb runs. */
|
||||
PyEval_SaveThread ();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue