2002-08-26 Joel Brobecker <brobecker@gnat.com>
authorMichael Snyder <msnyder@vmware.com>
Tue, 27 Aug 2002 01:09:09 +0000 (01:09 +0000)
committerMichael Snyder <msnyder@vmware.com>
Tue, 27 Aug 2002 01:09:09 +0000 (01:09 +0000)
* 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  <msnyder@redhat.com>

* 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
gdb/breakpoint.c
gdb/cli/cli-script.c
gdb/testsuite/gdb.base/commands.exp

index eeb211a..b329639 100644 (file)
@@ -1,3 +1,23 @@
+2002-08-26  Joel Brobecker  <brobecker@gnat.com>
+
+       * 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  <msnyder@redhat.com>
+
+       * 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  <kevinb@redhat.com>
 
        * rs6000-tdep.c (altivec_register_p): Restore function inadvertently
index 0f498af..630536f 100644 (file)
@@ -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. */
index 9aac6e6..2b23301 100644 (file)
@@ -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;
+}
 \f
 static void
 validate_comname (char *comname)
index dfaf965..3db28b1 100644 (file)
@@ -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