gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
# Copyright 2022 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/>.
|
|
|
|
|
|
|
|
# Test that GDB/MI commands preserve user selected context when
|
|
|
|
# passed --thread and/or --frame.
|
|
|
|
|
|
|
|
load_lib mi-support.exp
|
|
|
|
|
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
2022-04-05 00:08:22 +08:00
|
|
|
standard_testfile
|
gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
|
|
|
|
if {[build_executable $testfile.exp $testfile ${srcfile} "debug pthreads"] == -1} {
|
|
|
|
untested "failed to compile"
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
set main_break_line [gdb_get_line_number "main break line"]
|
|
|
|
|
|
|
|
set any "\[^\r\n\]*"
|
|
|
|
|
|
|
|
mi_clean_restart $binfile
|
|
|
|
mi_create_breakpoint "$srcfile:$main_break_line" "set breakpoint in main"
|
|
|
|
mi_run_cmd
|
|
|
|
mi_expect_stop "breakpoint-hit" "main" "" $srcfile $main_break_line \
|
|
|
|
{ "" "disp=\"keep\"" } "run to breakpoint in main"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 1.*" \
|
|
|
|
"info thread 1"
|
|
|
|
|
|
|
|
# Run -stack-info-depth in a different thread, the current thread
|
|
|
|
# should not change.
|
|
|
|
|
|
|
|
mi_gdb_test "-stack-info-depth --thread 3" \
|
|
|
|
"\\^done,depth=.*" \
|
|
|
|
"-stack-info-depth --thread 3"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 1.*" \
|
|
|
|
"info thread 2"
|
|
|
|
|
|
|
|
# Expect GDB to switch to thread 3.
|
|
|
|
mi_gdb_test "-thread-select 3" \
|
|
|
|
"\\^done,${any}new-thread-id=\"3\"${any}" \
|
|
|
|
"-thread-select 3"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 3.*" \
|
|
|
|
"info thread 3"
|
|
|
|
|
|
|
|
# Expect GDB to switch to thread 1.
|
|
|
|
mi_gdb_test "-thread-select --thread 2 1" \
|
|
|
|
"\\^done,${any}new-thread-id=\"1\"${any}" \
|
|
|
|
"-thread-select --thread 2 1"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 1.*" \
|
|
|
|
"info thread 4"
|
|
|
|
|
|
|
|
# Expect GDB to switch to thread 2.
|
|
|
|
mi_gdb_test "-thread-select --thread 2 2" \
|
|
|
|
"\\^done,.*" \
|
|
|
|
"-thread-select --thread 2 2"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 2.*" \
|
|
|
|
"info thread 5"
|
|
|
|
|
|
|
|
# Check we're in frame 0.
|
|
|
|
mi_gdb_test "frame" \
|
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
2022-04-05 00:08:22 +08:00
|
|
|
".*#0 .*child_sub_function .*" \
|
gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
"frame 1"
|
|
|
|
|
|
|
|
# Ask about a different frame in the current thread, the current frame
|
|
|
|
# should not change.
|
|
|
|
mi_gdb_test "-stack-info-frame --thread 2 --frame 1" \
|
|
|
|
"\\^done,frame=\{level=\"1\".*" \
|
|
|
|
"-stack-info-frame 1"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 2.*" \
|
|
|
|
"info thread 6"
|
|
|
|
|
|
|
|
mi_gdb_test "frame" \
|
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
2022-04-05 00:08:22 +08:00
|
|
|
".*#0 .*child_sub_function.*" \
|
gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
"frame 2"
|
|
|
|
|
|
|
|
|
|
|
|
# Ask about a different frame in a different thread. After this the
|
|
|
|
# current thread and frame should not have changed.
|
|
|
|
mi_gdb_test "-stack-info-frame --thread 3 --frame 1" \
|
|
|
|
"\\^done,frame=\{level=\"1\".*" \
|
|
|
|
"-stack-info-frame 2"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 2.*" \
|
|
|
|
"info thread 7"
|
|
|
|
|
|
|
|
mi_gdb_test "frame" \
|
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
2022-04-05 00:08:22 +08:00
|
|
|
".*#0 .*child_sub_function.*" \
|
gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
"frame 3"
|
|
|
|
|
|
|
|
# Select a different frame in the current thread. Despite the use of
|
|
|
|
# the --frame option, we do expect the currently selected frame to
|
|
|
|
# change.
|
|
|
|
mi_gdb_test "-stack-select-frame --thread 2 --frame 0 1" \
|
|
|
|
"\\^done" \
|
|
|
|
"--stack-select-frame 1"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 2.*" \
|
|
|
|
"info thread 8"
|
|
|
|
|
|
|
|
mi_gdb_test "frame" \
|
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
2022-04-05 00:08:22 +08:00
|
|
|
".*#1 .*child_function.*" \
|
gdb/mi: preserve user selected thread and frame when invoking MI commands
Fix for PR gdb/20684. When invoking MI commands with --thread and/or
--frame, the user selected thread and frame was not preserved:
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~"* 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~" 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7fffffffdf90:\n"
~" rip = 0x555555555207 in main (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60); saved rip = 0x7ffff7c5709b\n"
~" source language c.\n"
~" Arglist at 0x7fffffffdf80, args: \n"
~" Locals at 0x7fffffffdf80, Previous frame's sp is 0x7fffffffdf90\n"
~" Saved registers:\n "
~" rbp at 0x7fffffffdf80, rip at 0x7fffffffdf88\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="4"
(gdb)
info thread
&"info thread\n"
~" Id Target Id Frame \n"
~" 1 Thread 0x7ffff7c30740 (LWP 19302) \"user-selected-c\" main () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:60\n"
~" 2 Thread 0x7ffff7c2f700 (LWP 19306) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
~"* 3 Thread 0x7ffff742e700 (LWP 19307) \"user-selected-c\" child_sub_function () at /home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30\n"
^done
(gdb)
info frame
&"info frame\n"
~"Stack level 0, frame at 0x7ffff742dee0:\n"
~" rip = 0x555555555169 in child_sub_function (/home/uuu/gdb/gdb/testsuite/gdb.mi/user-selected-context-sync.c:30); saved rip = 0x555555555188\n"
~" called by frame at 0x7ffff742df00\n"
~" source language c.\n"
~" Arglist at 0x7ffff742ded0, args: \n"
~" Locals at 0x7ffff742ded0, Previous frame's sp is 0x7ffff742dee0\n"
~" Saved registers:\n "
~" rbp at 0x7ffff742ded0, rip at 0x7ffff742ded8\n"
^done
(gdb)
This caused problems for frontends that provide access to CLI because UI
may silently change the context for CLI commands (as demonstrated above).
This commit fixes the problem by restoring thread and frame in
mi_cmd_execute (). With this change, there are only two GDB/MI commands
that can change user selected context: -thread-select and -stack-select-frame.
This allows us to remove all and rather complicated logic of notifying
about user selected context change from mi_execute_command (), leaving it
to these two commands themselves to notify.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20684
2022-03-02 21:23:30 +08:00
|
|
|
"frame 4"
|
|
|
|
|
|
|
|
# Similar to the previous test, but this time the --frame option is
|
|
|
|
# the same as the frame we are selecting. We still expect GDB to
|
|
|
|
# update the currently selected frame.
|
|
|
|
mi_gdb_test "-stack-select-frame --thread 2 --frame 2 2" \
|
|
|
|
"\\^done" \
|
|
|
|
"--stack-select-frame 2"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 2.*" \
|
|
|
|
"info thread 9"
|
|
|
|
|
|
|
|
mi_gdb_test "frame" \
|
|
|
|
".*#2 0x.*" \
|
|
|
|
"frame 5"
|
|
|
|
|
|
|
|
# Now select a frame in a different thread. We expect both the
|
|
|
|
# currently selected thread, and the currently selected frame to be
|
|
|
|
# updated.
|
|
|
|
mi_gdb_test "-stack-select-frame --thread 1 --frame 0 0" \
|
|
|
|
"\\^done" \
|
|
|
|
"--stack-select-frame 3"
|
|
|
|
|
|
|
|
mi_gdb_test "thread" \
|
|
|
|
".*Current thread is 1.*" \
|
|
|
|
"info thread 10"
|
|
|
|
|
|
|
|
mi_gdb_test "frame" \
|
|
|
|
".*#0 main.*" \
|
|
|
|
"frame 6"
|