Re: RFA: New regression test for breakpoint command freeing

Jim Blandy
2003-12-13T20:11:20Z

Daniel Jacobowitz <drow@mvista.com> writes:
> On Sat, Dec 13, 2003 at 12:55:37AM -0500, Jim Blandy wrote:
> > + gdb_test_multiple "run" "run program with breakpoint commands" {
>
> No, please don't; any time that you issue an explicit "run" command in
> a testcase is probably a bug. Take a look at gdb_run_cmd:

Yes, of course; I should have known this. Sorry. Revised as below,
and committed:

gdb/testsuite/ChangeLog:
2003-12-13 Jim Blandy <jimb@redhat.com>

* gdb.base/freebpcmd.exp, gdb.base/freebpcmd.c: New test.

Index: gdb/testsuite/gdb.base/freebpcmd.exp
===================================================================
RCS file: gdb/testsuite/gdb.base/freebpcmd.exp
diff -N gdb/testsuite/gdb.base/freebpcmd.exp
*** gdb/testsuite/gdb.base/freebpcmd.exp 1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/freebpcmd.exp 13 Dec 2003 20:09:30 -0000
***************
*** 0 ****
--- 1,121 ----
+ # Copyright 2003 Free Software Foundation, Inc.
+
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+ # This is a regression test for the following bug, as of 2003-12-12:
+ #
+ # Set a breakpoint which will be hit many times. Attach a complex set
+ # of commands to it, including a "continue" command. Run the program,
+ # so that the breakpoint is hit, its commands get executed, and the
+ # program continues and hits the breakpoint again. You will see
+ # messages like "warning: Invalid control type in command structure.",
+ # or maybe GDB will crash.
+ #
+ # When the breakpoint is hit, bpstat_stop_status copies the
+ # breakpoint's command tree to the bpstat. bpstat_do_actions then
+ # calls execute_control_command to run the commands. The 'continue'
+ # command invokes the following chain of calls:
+ #
+ # continue_command
+ # -> clear_proceed_status
+ # -> bpstat_clear
+ # -> free_command_lines
+ # -> frees the commands we are currently running.
+ #
+ # When control does eventually return to execute_control_command, GDB
+ # continues to walk the tree of freed command nodes, resulting in the
+ # error messages and / or crashes.
+ #
+ # Since this bug depends on storage being reused between the time that
+ # we continue and the time that we fall back to bpstat_do_actions, the
+ # reproduction recipe is more delicate than I would like. I welcome
+ # suggestions for improving this.
+
+ set prms_id 0
+ set bug_id 0
+
+ set testfile "freebpcmd"
+ set srcfile ${testfile}.c
+ set srcfile1 ${testfile}1.c
+ set binfile ${objdir}/${subdir}/${testfile}
+
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+
+ gdb_test "break [gdb_get_line_number "euphonium"]" "" "set breakpoint"
+
+ # The goal of all this is to make sure that there's plenty of memory
+ # churn, and different amounts of it each time the inferior stops;
+ # this seems to make GDB crash more reliably.
+ set lines {{if (i%2) == 0}
+ {echo "even "}
+ {print i}
+ {else}
+ {echo "odd "}
+ {print i}
+ {end}
+ {set variable $foo = 0}
+ {set variable $j = 0}
+ {while $j < i}
+ {set variable $foo += $j}
+ {set variable $j++}
+ {end}
+ {print $foo}
+ {if i != 40}
+ {c}
+ {end}
+ {end}}
+
+ send_gdb "commands\n"
+ for {set i 0} {$i < [llength $lines]} {incr i} {
+ gdb_expect {
+ -re ".*>" {
+ send_gdb "[lindex $lines $i]\n"
+ }
+ -re "$gdb_prompt $" {
+ set reason "got top-level prompt early"
+ break
+ }
+ timeout {
+ set reason "timeout"
+ break
+ }
+ }
+ }
+ if {$i >= [llength $lines]} {
+ pass "send breakpoint commands"
+ } else {
+ fail "send breakpoint commands ($reason)"
+ }
+
+ gdb_run_cmd
+ gdb_test_multiple "" "run program with breakpoint commands" {
+ -re "warning: Invalid control type in command structure" {
+ fail "run program with breakpoint commands"
+ }
+ -re "$gdb_prompt $" {
+ pass "run program with breakpoint commands"
+ }
+ eof {
+ fail "run program with breakpoint commands (GDB died)"
+ }
+ }
Index: gdb/testsuite/gdb.base/freebpcmd.c
===================================================================
RCS file: gdb/testsuite/gdb.base/freebpcmd.c
diff -N gdb/testsuite/gdb.base/freebpcmd.c
*** gdb/testsuite/gdb.base/freebpcmd.c 1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/freebpcmd.c 13 Dec 2003 20:09:30 -0000
***************
*** 0 ****
--- 1,15 ----
+ int
+ main (int argc, char **argv)
+ {
+ int i;
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+
+ for (i = 0; i < 100; i++)
+ printf (">>> %d\n", i); /* euphonium */
+
+ return 0;
+ }