]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/testsuite] Fix timeout in gdb.base/bg-execution-repeat.exp
authorTom de Vries <tdevries@suse.de>
Wed, 26 Jun 2024 06:49:40 +0000 (08:49 +0200)
committerTom de Vries <tdevries@suse.de>
Wed, 26 Jun 2024 06:49:40 +0000 (08:49 +0200)
I ran into the following test failure with test-case
gdb.base/bg-execution-repeat.exp:
...
(gdb) PASS: gdb.base/bg-execution-repeat.exp: c&: repeat bg command
^M
Breakpoint 2, foo () at bg-execution-repeat.c:23^M
23        return 0; /* set break here */^M
print 1^M
$1 = 1^M
(gdb) PASS: gdb.base/bg-execution-repeat.exp: c&: input still accepted
FAIL: gdb.base/bg-execution-repeat.exp: c&: breakpoint hit 2 (timeout)
...

The failure can be easily reproduced by adding a sleep 5 here:
...
+    sleep 5
     gdb_test "print 1" " = 1" "input still accepted"
...

There's a race in the test-case, between:
- the command handled in the foreground: the "print 1" command, and
- the command handled in the background: the continue command.

The current way of dealing with this is by putting the inferior to sleep for 5
seconds:
...
  foo ();
  sleep (5);
  foo ();
...
with the aim that the "print 1" command will win the race.

This method is both slow and unreliable.

Fix this by making the inferior wait till the "print 1" command is done.

This reduces running time from ~11s to ~1s.

I also verified that the test-case still triggers on the original problem by
applying this gdb/infcmd.c patch:
...
-strip_bg_char (const char *args, int *bg_char_p)
+strip_bg_char (const char *_args, int *bg_char_p)
 {
-  const char *p;
+  char *args = const_cast<char *>(_args);
+  char *p;

   if (args == nullptr || *args == '\0')
     {
@@ -210,6 +211,7 @@ strip_bg_char (const char *args, int *bg_char_p)
       p--;
       while (p > args && isspace (p[-1]))
  p--;
+      *p = '\0';
...

Tested on x86_64-linux, with make-check-all.sh.

PR testsuite/31794
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31794

Reviewed-By: Guinevere Larsen <blarsen@redhat.com>
gdb/testsuite/gdb.base/bg-execution-repeat.c
gdb/testsuite/gdb.base/bg-execution-repeat.exp

index 2caa7d442f669d1b7d9099ef1078e336845798df..d5b48ee4f9430e155a6266a323c70ac38e9cc502 100644 (file)
@@ -23,11 +23,27 @@ foo (void)
   return 0; /* set break here */
 }
 
+static volatile int do_wait;
+
+static void
+wait (void)
+{
+  while (do_wait)
+    usleep (10 * 1000);
+}
+
 int
 main (void)
 {
+  alarm (60);
+
   foo ();
-  sleep (5);
+
+  do_wait = 1;
+  wait ();
+  /* do_wait set to 0 externally.  */
+
   foo ();
+
   return 0;
 }
index a4cc7daa70219d9e99c000cc8c95195d817eca64..35ddb34cd8f330c8b9f0b7ae74ef850a2f469b2f 100644 (file)
@@ -68,6 +68,15 @@ proc test {continue_cmd} {
     # stopped.
     gdb_test "print 1" " = 1" "input still accepted"
 
+    # With gdbserver, we cannot set memory while the inferior is running, so
+    # enable the "set var" command with an interrupt / continue& pair.
+    gdb_test -no-prompt-anchor "interrupt"
+
+    # Allow the breakpoint to trigger.
+    gdb_test -no-prompt-anchor "set var do_wait=0"
+
+    gdb_test -no-prompt-anchor "continue&"
+
     # Make sure we see a stop after the print, and not before.  Don't
     # expect a prompt, as we had resumed the inferior in the background.
     set test "breakpoint hit 2"