Skip to content

Commit

Permalink
Debugger: Fix debugging of multi-threaded programs
Browse files Browse the repository at this point in the history
- By original design, the debugger allows thread context switching only
  interactively, while in the Call Stack pane (in Stopped mode). This is
  being handled directly through GtkTreeView::cursor-changed event.
- However, this event was also getting triggered when clearing the latest
  thread's Call Stack after continuing the execution (Running mode).
- This behavior does not seem to have being intended, and it lead to a
  number of issues: stepping hangs, corruption of GDB output processing,
  unnecessary attempts at opening of source files corresponding to thread's
  call-stack frames.
- To avoid all of these issues, GtkTreeView::cursor-changed event is left
  unhandled while clearing the frames. Also the handler for thread-context
  switching is allowed processing only in debugger's Stopped mode to enforce
  the intended behavior.
  • Loading branch information
nomadbyte committed Mar 10, 2023
1 parent dc6980e commit aa40d7c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
4 changes: 4 additions & 0 deletions debugger/src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,10 @@ static void on_select_thread(int thread_id)
{
gboolean success;

/* interactive use - only when in stopped state */
if (debug_state != DBS_STOPPED)
return;

if (stack)
remove_stack_markers();

Expand Down
22 changes: 21 additions & 1 deletion debugger/src/stree.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static select_frame_cb select_frame = NULL;
static select_thread_cb select_thread = NULL;
static move_to_line_cb move_to_line = NULL;

/* signal handler ids */
static guint cursor_changed_hid = 0;

/* tree view, model and store handles */
static GtkWidget *tree = NULL;
static GtkTreeModel *model = NULL;
Expand Down Expand Up @@ -353,6 +356,7 @@ static void on_render_address (GtkTreeViewColumn *tree_column, GtkCellRenderer *
}
}


/*
* inits stack trace tree
*/
Expand Down Expand Up @@ -382,7 +386,7 @@ GtkWidget* stree_init(move_to_line_cb ml, select_thread_cb st, select_frame_cb s
gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree), FALSE);

/* connect signals */
g_signal_connect(G_OBJECT(tree), "cursor-changed", G_CALLBACK (on_cursor_changed), NULL);
cursor_changed_hid = g_signal_connect(G_OBJECT(tree), "cursor-changed", G_CALLBACK (on_cursor_changed), NULL);

/* for clicking on already selected frame */
g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(on_msgwin_button_press), NULL);
Expand Down Expand Up @@ -464,7 +468,14 @@ void stree_add(GList *frames)
*/
void stree_clear(void)
{
/* removing nodes from tree triggers the "cursor-changed" event;
* in this context we don't need to process it,
* so the signal handler should be disconnected before the clear
* and reconnected properly afterwards
*/
g_signal_handler_block(G_OBJECT(tree), cursor_changed_hid);
gtk_tree_store_clear(store);
g_signal_handler_unblock(G_OBJECT(tree), cursor_changed_hid);
}

/*
Expand Down Expand Up @@ -566,8 +577,17 @@ void stree_remove_frames(void)
if (find_thread_iter (active_thread_id, &thread_iter) &&
gtk_tree_model_iter_children(model, &child, &thread_iter))
{
/* removing nodes from tree triggers the "cursor-changed" event;
* in this context we don't need to process it,
* so the signal handler should be disconnected before the removes
* and reconnected properly afterwards
*/
g_signal_handler_block(G_OBJECT(tree), cursor_changed_hid);

while(gtk_tree_store_remove(GTK_TREE_STORE(model), &child))
;

g_signal_handler_unblock(G_OBJECT(tree), cursor_changed_hid);
}
}

Expand Down

0 comments on commit aa40d7c

Please sign in to comment.