aboutsummaryrefslogtreecommitdiff
path: root/gdb/stack.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2020-10-30 18:26:15 +0100
committerPedro Alves <pedro@palves.net>2020-10-30 01:01:12 +0000
commit79952e69634bd02029e79676a38915de60052e89 (patch)
tree74f734787fcea919e5f6166aef3775147e7946a7 /gdb/stack.c
parent4dd5c35212cf4685bb14f7709508de22a36e7dc2 (diff)
downloadgdb-79952e69634bd02029e79676a38915de60052e89.zip
gdb-79952e69634bd02029e79676a38915de60052e89.tar.gz
gdb-79952e69634bd02029e79676a38915de60052e89.tar.bz2
Make scoped_restore_current_thread's cdtors exception free (RFC)
If the remote target closes while we're reading registers/memory for restoring the selected frame in scoped_restore_current_thread's dtor, the corresponding TARGET_CLOSE_ERROR error is swallowed by the scoped_restore_current_thread's dtor, because letting exceptions escape from a dtor is bad. It isn't great to lose that errors like that, though. I've been thinking about how to avoid it, and I came up with this patch. The idea here is to make scoped_restore_current_thread's dtor do as little as possible, to avoid any work that might throw in the first place. And to do that, instead of having the dtor call restore_selected_frame, which re-finds the previously selected frame, just record the frame_id/level of the desired selected frame, and have get_selected_frame find the frame the next time it is called. In effect, this implements most of Cagney's suggestion, here: /* On demand, create the selected frame and then return it. If the selected frame can not be created, this function prints then throws an error. When MESSAGE is non-NULL, use it for the error message, otherwize use a generic error message. */ /* FIXME: cagney/2002-11-28: At present, when there is no selected frame, this function always returns the current (inner most) frame. It should instead, when a thread has previously had its frame selected (but not resumed) and the frame cache invalidated, find and then return that thread's previously selected frame. */ extern struct frame_info *get_selected_frame (const char *message); The only thing missing to fully implement that would be to make reinit_frame_cache just clear selected_frame instead of calling select_frame(NULL), and the call select_frame(NULL) explicitly in the places where we really wanted reinit_frame_cache to go back to the current frame too. That can done separately, though, I'm not proposing to do that in this patch. Note that this patch renames restore_selected_frame to lookup_selected_frame, and adds a new restore_selected_frame function that doesn't throw, to be paired with the also-new save_selected_frame function. There's a restore_selected_frame function in infrun.c that I think can be replaced by the new one in frame.c. Also done in this patch is make the get_selected_frame's parameter be optional, so that we don't have to pass down nullptr explicitly all over the place. lookup_selected_frame should really move from thread.c to frame.c, but I didn't do that here, just to avoid churn in the patch while it collects comments. I did make it extern and declared it in frame.h already, preparing for the move. I will do the move as a follow up patch if people agree with this approach. Incidentally, this patch alone would fix the crashes fixed by the previous patches in the series, because with this, scoped_restore_current_thread's constructor doesn't throw either. gdb/ChangeLog: * blockframe.c (block_innermost_frame): Use get_selected_frame. * frame.c (scoped_restore_selected_frame::scoped_restore_selected_frame): Use save_selected_frame. Save language as well. (scoped_restore_selected_frame::~scoped_restore_selected_frame): Use restore_selected_frame, and restore language as well. (selected_frame_id, selected_frame_level): New. (selected_frame): Update comments. (save_selected_frame, restore_selected_frame): New. (get_selected_frame): Use lookup_selected_frame. (get_selected_frame_if_set): Delete. (select_frame): Record selected_frame_level and selected_frame_id. * frame.h (scoped_restore_selected_frame) <m_level, m_lang>: New fields. (get_selected_frame): Make 'message' parameter optional. (get_selected_frame_if_set): Delete declaration. (select_frame): Update comments. (save_selected_frame, restore_selected_frame) (lookup_selected_frame): Declare. * gdbthread.h (scoped_restore_current_thread) <m_lang>: New field. * infrun.c (struct infcall_control_state) <selected_frame_level>: New field. (save_infcall_control_state): Use save_selected_frame. (restore_selected_frame): Delete. (restore_infcall_control_state): Use restore_selected_frame. * stack.c (select_frame_command_core, frame_command_core): Use get_selected_frame. * thread.c (restore_selected_frame): Rename to ... (lookup_selected_frame): ... this and make extern. Select the current frame if the frame level is -1. (scoped_restore_current_thread::restore): Also restore the language. (scoped_restore_current_thread::~scoped_restore_current_thread): Don't try/catch. (scoped_restore_current_thread::scoped_restore_current_thread): Save the language as well. Use save_selected_frame. Change-Id: I73fd1cfc40d8513c28e5596383b7ecd8bcfe700f
Diffstat (limited to 'gdb/stack.c')
-rw-r--r--gdb/stack.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/gdb/stack.c b/gdb/stack.c
index 4ba5500..83c3366 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1842,9 +1842,9 @@ trailing_outermost_frame (int count)
static void
select_frame_command_core (struct frame_info *fi, bool ignored)
{
- struct frame_info *prev_frame = get_selected_frame_if_set ();
+ frame_info *prev_frame = get_selected_frame ();
select_frame (fi);
- if (get_selected_frame_if_set () != prev_frame)
+ if (get_selected_frame () != prev_frame)
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
}
@@ -1863,10 +1863,9 @@ select_frame_for_mi (struct frame_info *fi)
static void
frame_command_core (struct frame_info *fi, bool ignored)
{
- struct frame_info *prev_frame = get_selected_frame_if_set ();
-
+ frame_info *prev_frame = get_selected_frame ();
select_frame (fi);
- if (get_selected_frame_if_set () != prev_frame)
+ if (get_selected_frame () != prev_frame)
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
else
print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);