From e1e8bbecd36924ac3fbf4cc09ea1a641e65b3f6c Mon Sep 17 00:00:00 2001 From: sgranjoux Date: Wed, 3 Oct 2007 20:48:54 +0000 Subject: [PATCH] * plugins/debug-manager/command.c, plugins/debug-manager/queue.c: Asynchronous command can abort other commands in queue Resynchronize debugger state when a command is cancelled * plugins/debug-manager/breakpoints.c: Free BreakpointItem only when it is not used anymore * plugins/gdb/plugin.c: Do not return TRUE if the callback and/or ready signal is not used * plugins/gdb/debugger.c: Fix a crash, return correct state when debugger is stopped git-svn-id: http://svn.gnome.org/svn/anjuta/trunk@3193 1dbfb86a-d425-0410-a06b-cb591aac69f6 --- ChangeLog | 16 +++++ plugins/debug-manager/breakpoints.c | 36 ++++++---- plugins/debug-manager/command.c | 12 ++-- plugins/debug-manager/queue.c | 137 +++++++++++++++++++++--------------- plugins/gdb/debugger.c | 18 ++++- plugins/gdb/plugin.c | 21 ------ 6 files changed, 141 insertions(+), 99 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c11ec9c..9f7a3fd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-10-03 Sebastien Granjoux + + * plugins/debug-manager/command.c, + plugins/debug-manager/queue.c: + Asynchronous command can abort other commands in queue + Resynchronize debugger state when a command is cancelled + + * plugins/debug-manager/breakpoints.c: + Free BreakpointItem only when it is not used anymore + + * plugins/gdb/plugin.c: + Do not return TRUE if the callback and/or ready signal is not used + + * plugins/gdb/debugger.c: + Fix a crash, return correct state when debugger is stopped + 2007-10-01 Sebastien Granjoux * plugins/project-wizard/autogen.c: diff --git a/plugins/debug-manager/breakpoints.c b/plugins/debug-manager/breakpoints.c index cfa33810..03199f17 100644 --- a/plugins/debug-manager/breakpoints.c +++ b/plugins/debug-manager/breakpoints.c @@ -85,7 +85,7 @@ struct _BreakpointItem GtkTreeIter iter; gboolean link; - gboolean keep; /* Do not free memory */ + guint in_use; /* Do not free memory */ }; struct _BreakpointsDBase @@ -379,13 +379,15 @@ breakpoint_item_free (BreakpointItem *bi) g_return_if_fail (bi != NULL); anjuta_breakpoint_free (bi->bp); + bi->bp = NULL; if (bi->editor != NULL) { g_object_remove_weak_pointer (G_OBJECT (bi->editor), (gpointer *)(gpointer)&bi->editor); + bi->editor = NULL; } - g_free (bi); + if (bi->in_use == 0) g_free (bi); } /* Private callback functions @@ -453,6 +455,7 @@ breakpoint_item_update_in_ui (BreakpointItem *bi, const IAnjutaDebuggerBreakpoin { if (bi->bp->enable != bp->enable) { + bi->in_use++; dma_queue_enable_breakpoint ( bi->bd->debugger, bi->bp->id, @@ -516,13 +519,6 @@ breakpoint_item_update_in_ui (BreakpointItem *bi, const IAnjutaDebuggerBreakpoin static void breakpoint_item_remove_in_ui (BreakpointItem *bi, const IAnjutaDebuggerBreakpoint* bp) { - if (bi->keep == TRUE) - { - /* Keep breakpoint */ - bi->keep = FALSE; - return; - } - /* Delete breakpoint marker from screen */ set_breakpoint_in_editor (bi, BREAKPOINT_NONE, FALSE); @@ -610,6 +606,7 @@ breakpoints_dbase_add_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi) { /* Breakpoint already exist, remove it first */ bi->bp->temporary = FALSE; + bi->in_use++; dma_queue_remove_breakpoint ( bd->debugger, bi->bp->id, @@ -619,6 +616,7 @@ breakpoints_dbase_add_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi) /* Add breakpoint in debugger */ if (bi->bp->type & IANJUTA_DEBUGGER_BREAK_ON_LINE) { + bi->in_use++; dma_queue_add_breakpoint_at_line ( bd->debugger, bi->bp->file, @@ -628,6 +626,7 @@ breakpoints_dbase_add_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi) } else if (bi->bp->type & IANJUTA_DEBUGGER_BREAK_ON_FUNCTION) { + bi->in_use++; dma_queue_add_breakpoint_at_function ( bd->debugger, bi->bp->file == NULL ? "" : bi->bp->file, @@ -637,6 +636,7 @@ breakpoints_dbase_add_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi) } else if (bi->bp->type & IANJUTA_DEBUGGER_BREAK_ON_ADDRESS) { + bi->in_use++; dma_queue_add_breakpoint_at_address ( bd->debugger, bi->bp->address, @@ -664,6 +664,7 @@ breakpoints_dbase_remove_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi) if (bd->debugger != NULL) { /* Remove breakpoint in debugger first */ + bi->in_use++; dma_queue_remove_breakpoint ( bd->debugger, bi->bp->id, @@ -686,6 +687,7 @@ breakpoints_dbase_enable_breakpoint (BreakpointsDBase *bd, BreakpointItem *bi, g if (bd->debugger != NULL) { /* Update breakpoint in debugger firt */ + bi->in_use++; dma_queue_enable_breakpoint ( bd->debugger, bi->bp->id, @@ -1132,16 +1134,25 @@ static void on_breakpoint_callback (const gpointer data, gpointer user_data, GError* err) { const IAnjutaDebuggerBreakpoint* breakpoint = (const IAnjutaDebuggerBreakpoint*)data; - + BreakpointItem *bi = (BreakpointItem *)user_data; + + bi->in_use--; + if (bi->bp == NULL) + { + /* Finish freeing BreakpointItem */ + if (bi->in_use == 0) g_free (bi); + return; + } + if (err == NULL) { if ((breakpoint != NULL) && (breakpoint->type & IANJUTA_DEBUGGER_BREAK_REMOVED)) { - breakpoint_item_remove_in_ui ((BreakpointItem *)user_data, breakpoint); + breakpoint_item_remove_in_ui (bi, breakpoint); } else { - breakpoint_item_update_in_ui ((BreakpointItem *)user_data, breakpoint); + breakpoint_item_update_in_ui (bi, breakpoint); } } } @@ -1301,6 +1312,7 @@ breakpoint_enable_disable (GtkTreeModel *model, GtkTreeIter iter, BreakpointsDBa if (bd->debugger != NULL) { + bi->in_use++; dma_queue_enable_breakpoint ( bd->debugger, bi->bp->id, diff --git a/plugins/debug-manager/command.c b/plugins/debug-manager/command.c index 8b169764..aef0819f 100644 --- a/plugins/debug-manager/command.c +++ b/plugins/debug-manager/command.c @@ -132,10 +132,10 @@ typedef enum NEED_DEBUGGER_STOPPED | NEED_DEBUGGER_STARTED, DMA_QUIT_COMMAND = QUIT_COMMAND | CANCEL_ALL_COMMAND | STOP_DEBUGGER | - ASYNCHRONOUS | NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, + NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, DMA_ABORT_COMMAND = ABORT_COMMAND | CANCEL_ALL_COMMAND | STOP_DEBUGGER | - ASYNCHRONOUS | NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, + NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_USER_COMMAND = USER_COMMAND | NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, @@ -165,16 +165,16 @@ typedef enum NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_ENABLE_BREAK_COMMAND = ENABLE_BREAK_COMMAND | - NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, + NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_IGNORE_BREAK_COMMAND = IGNORE_BREAK_COMMAND | - NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, + NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_CONDITION_BREAK_COMMAND = CONDITION_BREAK_COMMAND | - NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, + NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_REMOVE_BREAK_COMMAND = REMOVE_BREAK_COMMAND | - NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, + NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, DMA_INFO_SHAREDLIB_COMMAND = INFO_SHAREDLIB_COMMAND | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, diff --git a/plugins/debug-manager/queue.c b/plugins/debug-manager/queue.c index 1eb1cd3e..3afd79d3 100644 --- a/plugins/debug-manager/queue.c +++ b/plugins/debug-manager/queue.c @@ -27,9 +27,7 @@ #include "queue.h" -#ifndef DEBUG -# define DEBUG -#endif +/*#define DEBUG*/ #include #include @@ -150,48 +148,6 @@ dma_debugger_queue_clear (DmaDebuggerQueue *self) self->prepend_command = 0; } - -static gboolean -dma_queue_check_state (DmaDebuggerQueue *self, DmaQueueCommand* cmd) -{ - IAnjutaDebuggerState state; - - if (self->prepend_command) - { - /* Prepend command use debugger state or current command state */ - if (self->last != NULL) - { - state = dma_command_is_going_to_state (self->last); - if (state == IANJUTA_DEBUGGER_BUSY) - { - state = self->debugger_state; - } - } - else - { - state = self->debugger_state; - } - } - else - { - /* Append command use queue state */ - state = self->queue_state; - } - - /* Only the debugger can be busy */ - g_return_val_if_fail (state != IANJUTA_DEBUGGER_BUSY, FALSE); - - if (!dma_command_is_valid_in_state (cmd, state)) - { - g_warning ("Cancel command %x, debugger in state %d\n", dma_command_get_type (cmd), state); - return FALSE; - } - else - { - /* State is right */ - return TRUE; - } -} static void dma_queue_emit_debugger_state (DmaDebuggerQueue *self, IAnjutaDebuggerState state, GError* err) @@ -326,19 +282,22 @@ dma_debugger_queue_complete (DmaDebuggerQueue *self, IAnjutaDebuggerState state) /* Emit new state if necessary */ dma_queue_emit_debugger_state (self, state, NULL); - if ((self->last != NULL) && (state != IANJUTA_DEBUGGER_BUSY)) + if (state != IANJUTA_DEBUGGER_BUSY) { - if (dma_command_is_going_to_state (self->last) != state) + if (self->last != NULL) { - /* Command end in an unexpected state, - * Remove invalid following command */ - dma_queue_cancel_unexpected (self, state); - } + if (dma_command_is_going_to_state (self->last) != state) + { + /* Command end in an unexpected state, + * Remove invalid following command */ + dma_queue_cancel_unexpected (self, state); + } - /* Remove current command */ - DEBUG_PRINT("end command %x", dma_command_get_type (self->last)); - dma_command_free (self->last); - self->last = NULL; + /* Remove current command */ + DEBUG_PRINT("end command %x", dma_command_get_type (self->last)); + dma_command_free (self->last); + self->last = NULL; + } /* Send next command */ dma_debugger_queue_execute (self); @@ -401,6 +360,58 @@ dma_debugger_queue_execute (DmaDebuggerQueue *self) } static gboolean +dma_queue_check_state (DmaDebuggerQueue *self, DmaQueueCommand* cmd) +{ + gboolean recheck; + + for (recheck = FALSE; recheck != TRUE; recheck = TRUE) + { + IAnjutaDebuggerState state; + + if (self->prepend_command) + { + /* Prepend command use debugger state or current command state */ + if (self->last != NULL) + { + state = dma_command_is_going_to_state (self->last); + if (state == IANJUTA_DEBUGGER_BUSY) + { + state = self->debugger_state; + } + } + else + { + state = self->debugger_state; + } + } + else + { + /* Append command use queue state */ + state = self->queue_state; + } + + /* Only the debugger can be busy */ + g_return_val_if_fail (state != IANJUTA_DEBUGGER_BUSY, FALSE); + + if (dma_command_is_valid_in_state (cmd, state)) + { + /* State is right */ + return TRUE; + } + + g_warning ("Cancel command %x, debugger in state %d\n", dma_command_get_type (cmd), state); + + /* Check if synchronization is still ok */ + state = ianjuta_debugger_get_state (self->debugger, NULL); + dma_debugger_queue_complete (self, state); + + /* Check again */ + } + + return FALSE; +} + +static gboolean dma_debugger_activate_plugin (DmaDebuggerQueue* self, const gchar *mime_type) { AnjutaPluginManager *plugin_manager; @@ -567,14 +578,26 @@ dma_debugger_queue_append (DmaDebuggerQueue *self, DmaQueueCommand *cmd) DEBUG_PRINT("current %x", self->last == NULL ? 0 : dma_command_get_type (self->last)); DEBUG_PRINT("queue %x", self->queue->head == NULL ? 0 : dma_command_get_type (self->queue->head->data)); - if (dma_queue_check_state(self, cmd)) + if ((self->debugger != NULL) && dma_queue_check_state(self, cmd)) { /* If command is asynchronous stop current command */ if (dma_command_has_flag (cmd, ASYNCHRONOUS)) { + IAnjutaDebuggerState state; + + state = dma_command_is_going_to_state (cmd); + if (state != IANJUTA_DEBUGGER_BUSY) + { + /* Command is changing debugger state */ + dma_queue_cancel_unexpected (self, state); + } + + /* Append command at the beginning */ + g_queue_push_head (self->queue, cmd); + dma_debugger_queue_complete (self, self->debugger_state); } - if (self->prepend_command == 0) + else if (self->prepend_command == 0) { /* Append command at the end (in the queue) */ IAnjutaDebuggerState state; diff --git a/plugins/gdb/debugger.c b/plugins/gdb/debugger.c index 5c302839..452ce981 100644 --- a/plugins/gdb/debugger.c +++ b/plugins/gdb/debugger.c @@ -82,6 +82,7 @@ struct _DebuggerPriv gboolean prog_is_running; gboolean prog_is_attached; gboolean prog_is_loaded; + gboolean debugger_is_started; guint debugger_is_busy; gint post_execution_flag; @@ -222,7 +223,8 @@ debugger_initialize (Debugger *debugger) debugger->priv->parent_win = NULL; debugger->priv->search_dirs = NULL; debugger->priv->launcher = anjuta_launcher_new (); - + + debugger->priv->debugger_is_started = FALSE; debugger->priv->prog_is_running = FALSE; debugger->priv->debugger_is_busy = 0; debugger->priv->starting = FALSE; @@ -466,10 +468,14 @@ debugger_get_state (Debugger *debugger) { return IANJUTA_DEBUGGER_PROGRAM_LOADED; } - else + else if (debugger->priv->debugger_is_started) { return IANJUTA_DEBUGGER_STARTED; } + else + { + return IANJUTA_DEBUGGER_STOPPED; + } } } @@ -835,8 +841,11 @@ debugger_start (Debugger *debugger, const GList *search_dirs, ret = anjuta_launcher_execute (launcher, command_str, on_gdb_output_arrived, debugger); - if (ret) + if (ret) + { + debugger->priv->debugger_is_started = TRUE; debugger->priv->prog_is_loaded = prog != NULL; + } anjuta_launcher_set_encoding (launcher, "ISO-8859-1"); if (debugger->priv->output_callback != NULL) @@ -1492,6 +1501,8 @@ on_gdb_terminated (AnjutaLauncher *launcher, debugger_stop_terminal (debugger); debugger->priv->prog_is_running = FALSE; debugger->priv->term_is_running = FALSE; + debugger->priv->prog_is_attached = FALSE; + debugger->priv->prog_is_loaded = FALSE; debugger->priv->term_pid = -1; debugger->priv->debugger_is_busy = 0; debugger->priv->skip_next_prompt = FALSE; @@ -1507,6 +1518,7 @@ on_gdb_terminated (AnjutaLauncher *launcher, g_signal_emit_by_name (debugger->priv->instance, "debugger-stopped", err); } if (err != NULL) g_error_free (err); + debugger->priv->debugger_is_started = FALSE; } static void diff --git a/plugins/gdb/plugin.c b/plugins/gdb/plugin.c index 51acf7b7..35e83cd5 100644 --- a/plugins/gdb/plugin.c +++ b/plugins/gdb/plugin.c @@ -677,9 +677,6 @@ ibreakpoint_debugger_add_breakpoint_at_line (IAnjutaBreakpointDebugger *plugin, { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (file == NULL) return TRUE; - debugger_add_breakpoint_at_line (this->debugger, file, line, callback, user_data); return TRUE; @@ -690,9 +687,6 @@ ibreakpoint_debugger_add_breakpoint_at_function (IAnjutaBreakpointDebugger *plug { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (function == NULL) return TRUE; - debugger_add_breakpoint_at_function (this->debugger, *file == '\0' ? NULL : file, function, callback, user_data); return TRUE; @@ -703,9 +697,6 @@ ibreakpoint_debugger_add_breakpoint_at_address (IAnjutaBreakpointDebugger *plugi { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (address == 0) return TRUE; - debugger_add_breakpoint_at_address (this->debugger, address, callback, user_data); return TRUE; @@ -716,9 +707,6 @@ ibreakpoint_debugger_enable_breakpoint (IAnjutaBreakpointDebugger *plugin, guint { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (id == 0) return TRUE; - debugger_enable_breakpoint (this->debugger, id, enable, callback, user_data); return TRUE; @@ -729,9 +717,6 @@ ibreakpoint_debugger_ignore_breakpoint (IAnjutaBreakpointDebugger *plugin, guint { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (id == 0) return TRUE; - debugger_ignore_breakpoint (this->debugger, id, ignore, callback, user_data); return TRUE; @@ -742,9 +727,6 @@ ibreakpoint_debugger_condition_breakpoint (IAnjutaBreakpointDebugger *plugin, gu { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (id == 0) return TRUE; - debugger_condition_breakpoint (this->debugger, id, condition, callback, user_data); return TRUE; @@ -755,9 +737,6 @@ ibreakpoint_debugger_remove_breakpoint (IAnjutaBreakpointDebugger *plugin, guint { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); - /* NULL breakpoint is used to detect available feature */ - if (id == 0) return TRUE; - debugger_remove_breakpoint (this->debugger, id, callback, user_data); return TRUE; -- 2.11.4.GIT