gdb/testsuite: fix intermittent failures in gdb.mi/mi-cmd-user-context.exp
authorSimon Marchi <simon.marchi@efficios.com>
Mon, 4 Apr 2022 16:08:22 +0000 (12:08 -0400)
committerSimon Marchi <simon.marchi@polymtl.ca>
Tue, 5 Apr 2022 12:01:50 +0000 (08:01 -0400)
commit9b571e28984a7fb757962be477322f89d2366c80
tree118970e8c80f0d8e0fa2450b85fbb16c13048076
parentd5ce6f2dcacf9809fb7a29a69c4b98e0320c3c94
gdb/testsuite: fix intermittent failures in gdb.mi/mi-cmd-user-context.exp

I got failures like this once on a CI:

    frame^M
    &"frame\n"^M
    ~"#0  child_sub_function () at /home/jenkins/workspace/binutils-gdb_master_build/arch/amd64/target_board/unix/src/binutils-gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:33\n"^M
    ~"33\t    dummy = !dummy; /* thread loop line */\n"^M
    ^done^M
    (gdb) ^M
    FAIL: gdb.mi/mi-cmd-user-context.exp: frame 1 (unexpected output)

The problem is that the test expects the following regexp:

  ".*#0  0x.*"

And that typically works, when the output of the frame command looks
like:

  #0  0x00005555555551bb in child_sub_function () at ...

Note the lack of hexadecimal address in the failing case.  Whether or
not the hexadecimal address is printed (roughly) depends on whether the
current PC is at the beginning of a line.  So depending on where thread
2 was when GDB stopped it (after thread 1 hit its breakpoint), we can
get either output.  Adjust the regexps to not expect an hexadecimal
prefix (0x) but a function name instead (either child_sub_function or
child_function).  That one is always printed, and is also a good check
that we are in the frame we expect.

Note that for test "frame 5", we are showing a pthread frame (on my
system), so the function name is internal to pthread, not something we
can rely on.  In that case, it's almost certain that we are not at the
beginning of a line, or that we don't have debug info, so I think it's
fine to expect the hex prefix.

And for test "frame 6", it's ok to _not_ expect a hex prefix (what the
test currently does), since we are showing thread 1, which has hit a
breakpoint placed at the beginning of a line.

When testing this, Tom de Vries pointed out that the current test code
doesn't ensure that the child threads are in child_sub_function when
they are stopped.  If the scheduler chooses so, it is possible for the
child threads to be still in the pthread_barrier_wait or child_function
functions when they get stopped.  So that would be another racy failure
waiting to happen.

The only way I can think of to ensure the child threads are in the
child_sub_function function when they get stopped is to synchronize the
threads using some variables instead of pthread_barrier_wait.  So,
replace the barrier with an array of flags (one per child thread).  Each
child thread flips its flag in child_sub_function to allow the main
thread to make progress and eventually hit the breakpoint.

I copied user-selected-context-sync.c to a new mi-cmd-user-context.c and
made modifications to that, to avoid interfering with
user-selected-context-sync.exp.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29025
Change-Id: I919673bbf9927158beb0e8b7e9e980b8d65eca90
gdb/testsuite/gdb.mi/mi-cmd-user-context.c [new file with mode: 0644]
gdb/testsuite/gdb.mi/mi-cmd-user-context.exp