binutils-gdb/gdb/observable.c
Andrew Burgess b1f0f28418 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.
2021-10-05 10:05:40 +01:00

105 lines
3.3 KiB
C

/* GDB Notifications to Observers.
Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "observable.h"
#include "command.h"
#include "gdbcmd.h"
namespace gdb
{
namespace observers
{
bool observer_debug = false;
#define DEFINE_OBSERVABLE(name) decltype (name) name (# name)
DEFINE_OBSERVABLE (normal_stop);
DEFINE_OBSERVABLE (signal_received);
DEFINE_OBSERVABLE (end_stepping_range);
DEFINE_OBSERVABLE (signal_exited);
DEFINE_OBSERVABLE (exited);
DEFINE_OBSERVABLE (no_history);
DEFINE_OBSERVABLE (sync_execution_done);
DEFINE_OBSERVABLE (command_error);
DEFINE_OBSERVABLE (target_changed);
DEFINE_OBSERVABLE (executable_changed);
DEFINE_OBSERVABLE (inferior_created);
DEFINE_OBSERVABLE (inferior_execd);
DEFINE_OBSERVABLE (record_changed);
DEFINE_OBSERVABLE (solib_loaded);
DEFINE_OBSERVABLE (solib_unloaded);
DEFINE_OBSERVABLE (new_objfile);
DEFINE_OBSERVABLE (free_objfile);
DEFINE_OBSERVABLE (new_thread);
DEFINE_OBSERVABLE (thread_exit);
DEFINE_OBSERVABLE (thread_stop_requested);
DEFINE_OBSERVABLE (target_resumed);
DEFINE_OBSERVABLE (about_to_proceed);
DEFINE_OBSERVABLE (breakpoint_created);
DEFINE_OBSERVABLE (breakpoint_deleted);
DEFINE_OBSERVABLE (breakpoint_modified);
DEFINE_OBSERVABLE (traceframe_changed);
DEFINE_OBSERVABLE (architecture_changed);
DEFINE_OBSERVABLE (thread_ptid_changed);
DEFINE_OBSERVABLE (inferior_added);
DEFINE_OBSERVABLE (inferior_appeared);
DEFINE_OBSERVABLE (inferior_exit);
DEFINE_OBSERVABLE (inferior_removed);
DEFINE_OBSERVABLE (memory_changed);
DEFINE_OBSERVABLE (before_prompt);
DEFINE_OBSERVABLE (gdb_datadir_changed);
DEFINE_OBSERVABLE (command_param_changed);
DEFINE_OBSERVABLE (tsv_created);
DEFINE_OBSERVABLE (tsv_deleted);
DEFINE_OBSERVABLE (tsv_modified);
DEFINE_OBSERVABLE (inferior_call_pre);
DEFINE_OBSERVABLE (inferior_call_post);
DEFINE_OBSERVABLE (register_changed);
DEFINE_OBSERVABLE (user_selected_context_changed);
DEFINE_OBSERVABLE (source_styling_changed);
DEFINE_OBSERVABLE (current_source_symtab_and_line_changed);
DEFINE_OBSERVABLE (gdb_exiting);
} /* namespace observers */
} /* namespace gdb */
static void
show_observer_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Observer debugging is %s.\n"), value);
}
void _initialize_observer ();
void
_initialize_observer ()
{
add_setshow_boolean_cmd ("observer", class_maintenance,
&gdb::observers::observer_debug, _("\
Set observer debugging."), _("\
Show observer debugging."), _("\
When non-zero, observer debugging is enabled."),
NULL,
show_observer_debug,
&setdebuglist, &showdebuglist);
}