From c2b8ed2c806135f28c880b614ab8728a8c2afa65 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Tue, 27 Aug 2002 01:09:09 +0000 Subject: [PATCH] 2002-08-26 Joel Brobecker * cli/cli-script.c (copy_command_lines): New function. * defs.h (copy_command_lines): Export. * testsuite/gdb.base/commands.exp: New tests for commands attached to a temporary breakpoint, and for commands that delete the breakpoint they are attached to. 2002-08-26 Michael Snyder * breakpoint.c (bpstat_stop_status): Instead of copying the pointer to the breakpoint commands struct, make a new copy of the struct and point to that. (bpstat_clear): Free the commands struct. (bpstat_clear_actions): Free the commands struct. (bpstat_do_actions): Free the command actions. Also execute the local cleanups, instead of deleting them. (delete_breakpoint): Leave the commands field of the bpstat chain alone -- it will be freed later. --- gdb/ChangeLog | 20 +++++ gdb/breakpoint.c | 19 ++--- gdb/cli/cli-script.c | 30 ++++++++ gdb/testsuite/gdb.base/commands.exp | 115 ++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 13 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index eeb211a3cf3..b32963902c6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2002-08-26 Joel Brobecker + + * cli/cli-script.c (copy_command_lines): New function. + * defs.h (copy_command_lines): Export. + * testsuite/gdb.base/commands.exp: New tests for commands + attached to a temporary breakpoint, and for commands that + delete the breakpoint they are attached to. + +2002-08-26 Michael Snyder + + * breakpoint.c (bpstat_stop_status): Instead of copying the + pointer to the breakpoint commands struct, make a new copy + of the struct and point to that. + (bpstat_clear): Free the commands struct. + (bpstat_clear_actions): Free the commands struct. + (bpstat_do_actions): Free the command actions. Also execute + the local cleanups, instead of deleting them. + (delete_breakpoint): Leave the commands field of the bpstat + chain alone -- it will be freed later. + 2002-08-26 Kevin Buettner * rs6000-tdep.c (altivec_register_p): Restore function inadvertently diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 0f498af9957..630536f42fb 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1763,6 +1763,7 @@ bpstat_clear (bpstat *bsp) q = p->next; if (p->old_val != NULL) value_free (p->old_val); + free_command_lines (&p->commands); xfree (p); p = q; } @@ -1875,7 +1876,7 @@ bpstat_clear_actions (bpstat bs) { for (; bs != NULL; bs = bs->next) { - bs->commands = NULL; + free_command_lines (&bs->commands); if (bs->old_val != NULL) { value_free (bs->old_val); @@ -1944,11 +1945,9 @@ top: to look at, so start over. */ goto top; else - bs->commands = NULL; + free_command_lines (&bs->commands); } - - executing_breakpoint_commands = 0; - discard_cleanups (old_chain); + do_cleanups (old_chain); } /* This is the normal print function for a bpstat. In the future, @@ -2730,7 +2729,7 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint) /* We will stop here */ if (b->disposition == disp_disable) b->enable_state = bp_disabled; - bs->commands = b->commands; + bs->commands = copy_command_lines (b->commands); if (b->silent) bs->print = 0; if (bs->commands && @@ -6787,14 +6786,8 @@ delete_breakpoint (struct breakpoint *bpt) if (bs->breakpoint_at == bpt) { bs->breakpoint_at = NULL; - - /* we'd call bpstat_clear_actions, but that free's stuff and due - to the multiple pointers pointing to one item with no - reference counts found anywhere through out the bpstat's (how - do you spell fragile?), we don't want to free things twice -- - better a memory leak than a corrupt malloc pool! */ - bs->commands = NULL; bs->old_val = NULL; + /* bs->commands will be freed later. */ } /* On the chance that someone will soon try again to delete this same bp, we mark it as deleted before freeing its storage. */ diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 9aac6e6aaae..2b23301c6b3 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -1012,6 +1012,36 @@ make_cleanup_free_command_lines (struct command_line **arg) { return make_cleanup (do_free_command_lines_cleanup, arg); } + +struct command_line * +copy_command_lines (struct command_line *cmds) +{ + struct command_line *result = NULL; + + if (cmds) + { + result = (struct command_line *) xmalloc (sizeof (struct command_line)); + + result->next = copy_command_lines (cmds->next); + result->line = xstrdup (cmds->line); + result->control_type = cmds->control_type; + result->body_count = cmds->body_count; + if (cmds->body_count > 0) + { + int i; + + result->body_list = (struct command_line **) + xmalloc (sizeof (struct command_line *) * cmds->body_count); + + for (i = 0; i < cmds->body_count; i++) + result->body_list[i] = copy_command_lines (cmds->body_list[i]); + } + else + result->body_list = NULL; + } + + return result; +} static void validate_comname (char *comname) diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp index dfaf965ca99..3db28b187b6 100644 --- a/gdb/testsuite/gdb.base/commands.exp +++ b/gdb/testsuite/gdb.base/commands.exp @@ -440,7 +440,120 @@ proc deprecated_command_test {} { "deprecate with no arguments" } +proc bp_deleted_in_command_test {} { + global gdb_prompt + + gdb_test "set args 1" "" "set args in bp_deleted_in_command_test" + delete_breakpoints + + # Create a breakpoint, and associate a command-list to it, with + # one command that deletes this breakpoint. + gdb_test "break factorial" \ + "Breakpoint \[0-9\]+ at .*: file .*/run.c, line \[0-9\]+\." \ + "breakpoint in bp_deleted_in_command_test" + + send_gdb "commands\n" + gdb_expect { + -re "Type commands for when breakpoint .* is hit, one per line.*>" { + pass "begin commands in bp_deleted_in_command_test" + } + -re "$gdb_prompt $" {fail "begin commands in bp_deleted_in_command_test"} + timeout {fail "(timeout) begin commands bp_deleted_in_command_test"} + } + send_gdb "silent\n" + gdb_expect { + -re ">" {pass "add silent command"} + -re "$gdb_prompt $" {fail "add silent command"} + timeout {fail "(timeout) add silent command"} + } + send_gdb "clear factorial\n" + gdb_expect { + -re ">" {pass "add clear command"} + -re "$gdb_prompt $" {fail "add clear command"} + timeout {fail "(timeout) add clear command"} } + send_gdb "printf \"factorial command-list executed\\n\"\n" + gdb_expect { + -re ">" {pass "add printf command"} + -re "$gdb_prompt $" {fail "add printf command"} + timeout {fail "(timeout) add printf command"} + } + send_gdb "cont\n" + gdb_expect { + -re ">" {pass "add cont command"} + -re "$gdb_prompt $" {fail "add cont command"} + timeout {fail "(timeout) add cont command"} } + send_gdb "end\n" + gdb_expect { + -re "$gdb_prompt $" {pass "end commands"} + timeout {fail "(timeout) end commands"} + } + gdb_run_cmd + gdb_expect { + -re ".*factorial command-list executed.*1.*Program exited normally.*$gdb_prompt $" { + pass "run factorial until breakpoint" + } + -re ".*$gdb_prompt $" { + fail "run factorial until breakpoint" + } + default { fail "(timeout) run factorial until breakpoint" } + timeout { fail "(timeout) run factorial until breakpoint" } + } +} + +proc temporary_breakpoint_commands {} { + global gdb_prompt + + gdb_test "set args 1" "" "set args in temporary_breakpoint_commands" + delete_breakpoints + + # Create a temporary breakpoint, and associate a commands list to it. + # This test will verify that this commands list is executed when the + # breakpoint is hit. + gdb_test "tbreak factorial" \ + "Breakpoint \[0-9\]+ at .*: file .*/run.c, line \[0-9\]+\." \ + "breakpoint in temporary_breakpoint_commands" + + send_gdb "commands\n" + gdb_expect { + -re "Type commands for when breakpoint .* is hit, one per line.*>" { + pass "begin commands in bp_deleted_in_command_test" + } + -re "$gdb_prompt $" {fail "begin commands in bp_deleted_in_command_test"} + timeout {fail "(timeout) begin commands bp_deleted_in_command_test"} + } + send_gdb "silent\n" + gdb_expect { + -re ">" {pass "add silent tbreak command"} + -re "$gdb_prompt $" {fail "add silent tbreak command"} + timeout {fail "(timeout) add silent tbreak command"} + } + send_gdb "printf \"factorial tbreak commands executed\\n\"\n" + gdb_expect { + -re ">" {pass "add printf tbreak command"} + -re "$gdb_prompt $" {fail "add printf tbreak command"} + timeout {fail "(timeout) add printf tbreak command"} + } + send_gdb "cont\n" + gdb_expect { + -re ">" {pass "add cont tbreak command"} + -re "$gdb_prompt $" {fail "add cont tbreak command"} + timeout {fail "(timeout) add cont tbreak command"} } + send_gdb "end\n" + gdb_expect { + -re "$gdb_prompt $" {pass "end tbreak commands"} + timeout {fail "(timeout) end tbreak commands"} + } + + gdb_run_cmd + gdb_expect { + -re ".*factorial tbreak commands executed.*1.*Program exited normally.*" { + pass "run factorial until temporary breakpoint" + } + timeout { fail "(timeout) run factorial until temporary breakpoint" } + } +} + gdbvar_simple_if_test gdbvar_simple_while_test gdbvar_complex_if_while_test @@ -454,3 +567,5 @@ user_defined_command_test watchpoint_command_test test_command_prompt_position deprecated_command_test +bp_deleted_in_command_test +temporary_breakpoint_commands -- 2.30.2