This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

async intermediate continuations handling fix


The async mode uses intermediate continuations to implement the multiple
steps of a "step $n"-like operation.

In fetch_inferior_event, we decide if we're still in the middle of
a step multi, and if so, run the intermediate continuations.
It is the step_1_continuation's (an intermediate continuation)
job to decrease $n, and step one more time if $n is still >0.
It is also the continuations job to disable the longjmp
breakpoints.  This means that even in the 'step 1' case, or
'-exec-step, or next, or -exec-next', we also install an
intermediate continuation to disable the longjmp
breakpoints.

There are a couple of bugs related to this in the
current codebase. When we install the continuation, we
forget to run it on the last iteration step.  This means
that everytime we do a step, a new continuation is
placed in the queue, and it's never ran, even in the step 1
case.

Another problem, is that if a step command is interrupted
by a user breakpoint, we also leave the intermediate
continuations in the queue.

In the step n case, this is quite noticeable.  If the user
issues a 'step 2' command, and it is interrupted by a 
breakpoint, and then the user issues another 'step 2',
the continuations from the previous step will still
be in place.  When the first step in the 'step 2' command
finishes, the intermediate continuations are ran.  Now
there are two copies of step_1_continuation registered, 
both will run.  The second one will try to resume the inferior,
and it is already running...

To fix this we should also run the continuations in the
INF_EXEC_COMPLETE case.  The continuations themselves
are responsible for detecting if they should go on, or
if the step was interrupted.  That's already done,
but the checking will need a further tweak a bit
further down the non-stop series.

New test included that fails in async mode without
this patch.  A few iterations were needed to trigger
an error reliably.

Tested on x86_64-unknown-linux-gnu.

-- 
Pedro Alves
2008-04-08  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* inf-loop.c (inferior_event_handler): Also run the intermediate
	continuations in the INF_EXEC_COMPLETE case.

	gdb/testsuite/
	* gdb.base/step-break.exp, gdb.base/step-break.c: New files.

---
 gdb/inf-loop.c                        |    6 +++
 gdb/testsuite/gdb.base/step-break.c   |   32 ++++++++++++++++++
 gdb/testsuite/gdb.base/step-break.exp |   58 ++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+)

Index: src/gdb/inf-loop.c
===================================================================
--- src.orig/gdb/inf-loop.c	2008-03-27 00:11:00.000000000 +0000
+++ src/gdb/inf-loop.c	2008-03-27 19:37:36.000000000 +0000
@@ -91,6 +91,12 @@ inferior_event_handler (enum inferior_ev
       was_sync = sync_execution;
       async_enable_stdin ();
 
+      /* If we were doing a multi-step (eg: step n, next n), but it
+	 got interrupted by a breakpoint, still do the pending
+	 continuations.  The continuation itself is responsible for
+	 distinguishing the cases.  */
+      do_all_intermediate_continuations ();
+
       do_all_continuations ();
 
       if (current_language != expected_language)
Index: src/gdb/testsuite/gdb.base/step-break.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/step-break.c	2008-03-27 20:28:51.000000000 +0000
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 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 3 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, see <http://www.gnu.org/licenses/>.
+
+*/
+
+int
+main ()
+{
+    volatile int i = 1;
+
+    while (i > 0) /* place1 */
+      {
+	i++; /* place2 */
+	i++; /* place3, set breakpoint here  */
+      }
+
+    return 0;
+}
Index: src/gdb/testsuite/gdb.base/step-break.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/step-break.exp	2008-03-27 00:13:08.000000000 +0000
@@ -0,0 +1,58 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2008 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 3 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, see <http://www.gnu.org/licenses/>.  */
+# step-test.exp -- Expect script to test stepping in gdb
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set testfile step-break
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     untested step-break.exp
+     return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+   fail "Can't run to main"
+   return 0
+}
+
+set bp_location [gdb_get_line_number "set breakpoint here"]
+
+gdb_test "break $bp_location" \
+    "Breakpoint.*at.* file .*$srcfile, line $bp_location\\." \
+    "breakpoint line number"
+
+gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(\\) at .*$srcfile:$bp_location.*set breakpoint here.*" \
+    "run until breakpoint set at a line number"
+
+gdb_test "next 2" ".*place2.*" "next 2 (1)"
+gdb_test "next 2" ".*place3.*" "next 2 (2)"
+gdb_test "next 2" ".*place2.*" "next 2 (3)"
+gdb_test "next 2" ".*place3.*" "next 2 (4)"
+gdb_test "next 2" ".*place2.*" "next 2 (5)"
+gdb_test "next 2" ".*place3.*" "next 2 (6)"
+
+return 0

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]