aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/breakpoint.c23
-rw-r--r--gdb/cli/cli-script.c5
-rw-r--r--gdb/cli/cli-script.h2
4 files changed, 34 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a7c08e9..985ec69 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2003-12-21 Jim Blandy <jimb@redhat.com>
+
+ * breakpoint.c (bpstat_do_actions): To ensure that
+ clear_proceed_status doesn't free the command tree we're
+ evaluating out from under us, zero the bpstat's pointer to it, and
+ take care of freeing it ourselves.
+ * cli/cli-script.c (make_cleanup_free_command_lines): Make this
+ function externally visible.
+ * cli/cli-script.h (make_cleanup_free_command_lines): New
+ declaration.
+
2003-12-20 Mark Kettenis <kettenis@gnu.org>
* x86-64-tdep.c (x86_64_dwarf_regmap): Map the Return Address to
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index c535add..6a17368 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1992,7 +1992,6 @@ bpstat_do_actions (bpstat *bsp)
{
bpstat bs;
struct cleanup *old_chain;
- struct command_line *cmd;
/* Avoid endless recursion if a `source' command is contained
in bs->commands. */
@@ -2017,7 +2016,23 @@ top:
breakpoint_proceeded = 0;
for (; bs != NULL; bs = bs->next)
{
+ struct command_line *cmd;
+ struct cleanup *this_cmd_tree_chain;
+
+ /* Take ownership of the BSP's command tree, if it has one.
+
+ The command tree could legitimately contain commands like
+ 'step' and 'next', which call clear_proceed_status, which
+ frees stop_bpstat's command tree. To make sure this doesn't
+ free the tree we're executing out from under us, we need to
+ take ownership of the tree ourselves. Since a given bpstat's
+ commands are only executed once, we don't need to copy it; we
+ can clear the pointer in the bpstat, and make sure we free
+ the tree when we're done. */
cmd = bs->commands;
+ bs->commands = 0;
+ this_cmd_tree_chain = make_cleanup_free_command_lines (&cmd);
+
while (cmd != NULL)
{
execute_control_command (cmd);
@@ -2027,14 +2042,16 @@ top:
else
cmd = cmd->next;
}
+
+ /* We can free this command tree now. */
+ do_cleanups (this_cmd_tree_chain);
+
if (breakpoint_proceeded)
/* The inferior is proceeded by the command; bomb out now.
The bpstat chain has been blown away by wait_for_inferior.
But since execution has stopped again, there is a new bpstat
to look at, so start over. */
goto top;
- else
- free_command_lines (&bs->commands);
}
do_cleanups (old_chain);
}
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index cac5408..a8375a3 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -36,9 +36,6 @@
/* Prototypes for local functions */
-static struct cleanup *
- make_cleanup_free_command_lines (struct command_line **arg);
-
static enum command_control_type
recurse_read_control_structure (struct command_line *current_cmd);
@@ -1001,7 +998,7 @@ do_free_command_lines_cleanup (void *arg)
free_command_lines (arg);
}
-static struct cleanup *
+struct cleanup *
make_cleanup_free_command_lines (struct command_line **arg)
{
return make_cleanup (do_free_command_lines_cleanup, arg);
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 03cb841..fc5c203 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -47,6 +47,8 @@ extern void print_command_lines (struct ui_out *,
extern struct command_line * copy_command_lines (struct command_line *cmds);
+struct cleanup *make_cleanup_free_command_lines (struct command_line **arg);
+
/* Exported to gdb/infrun.c */
extern void execute_user_command (struct cmd_list_element *c, char *args);