mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-27 04:52:05 +08:00
b8b5466f0d
Tom de Vries reported some failures in this test: continue Continuing. [New inferior 2 (process 14967)] Thread 1.1 "vfork-follow-pa" hit Breakpoint 2, break_parent () at /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/vfork-follow-parent.c:23 23 } (gdb) FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to end of inferior 2 inferior 1 [Switching to inferior 1 [process 14961] (/home/vries/gdb_versions/devel/build/gdb/testsuite/outputs/gdb.base/vfork-follow-parent/vfork-follow-parent)] [Switching to thread 1.1 (process 14961)] #0 break_parent () at /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/vfork-follow-parent.c:23 23 } (gdb) PASS: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: inferior 1 continue Continuing. [Inferior 2 (process 14967) exited normally] (gdb) FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to break_parent (the program exited) Here, we continue both the vfork parent and child, since schedule-multiple is on. The child exits, which un-freezes the parent and makes an exit event available to GDB. We expect GDB to consume this exit event and present it to the user. Here, we see that GDB shows the parent hitting a breakpoint before showing the child exit. Because of the vfork, we know that chronologically, the child exiting must have happend before the parent hitting a breakpoint. However, scheduling being what it is, it is possible for the parent to un-freeze and exit quickly, such that when GDB pulls events out of the kernel, exit events for both processes are available. And then, GDB may chose at random to return the one for the parent first. This is what I imagine what causes the failure shown above. We could change the test to expect both possible outcomes, but I wanted to avoid complicating the .exp file that way. Instead, add a variable that the parent loops on that we set only after we confirmed the exit of the child. That should ensure that the order is always the same. Note that I wasn't able to reproduce the failure, so I can't tell if this fix really fixes the problem. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29021 Change-Id: Ibc8e527e0e00dac54b22021fe4d9d8ab0f3b28ad
81 lines
2.8 KiB
Plaintext
81 lines
2.8 KiB
Plaintext
# Copyright 2021-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 running into vfork while "detach-on-fork" is off and "follow-fork-mode"
|
|
# is parent. This shows a "Can not resume the parent process..." message. If
|
|
# the user wants to resume execution, they have to use either "set
|
|
# schedule-multiple on" or "set detach-on-fork on". Test these two resolution
|
|
# methods.
|
|
|
|
standard_testfile
|
|
|
|
if { [build_executable "failed to prepare" \
|
|
${testfile} ${srcfile}] } {
|
|
return
|
|
}
|
|
|
|
# Test running to the "Can not resume the parent..." message. Then, resolve
|
|
# the situation using the method in RESOLUTION_METHOD, either "detach-on-fork"
|
|
# or "schedule-multiple" (the two alternatives the message suggests to the
|
|
# user).
|
|
|
|
proc do_test { resolution_method } {
|
|
clean_restart $::binfile
|
|
|
|
gdb_test_no_output "set detach-on-fork off"
|
|
|
|
if { ![runto_main] } {
|
|
return
|
|
}
|
|
|
|
gdb_test "break break_parent"
|
|
|
|
gdb_test "continue" \
|
|
"Can not resume the parent process over vfork .*" \
|
|
"continue to vfork"
|
|
|
|
# Try to continue again from there, expecting the same message. It
|
|
# exercises a different code path in GDB.
|
|
gdb_test "continue" \
|
|
"Can not resume the parent process over vfork .*" \
|
|
"try to continue from vfork"
|
|
|
|
# Unblock the execution using the specified resolution method.
|
|
if { $resolution_method == "detach-on-fork" } {
|
|
# Make GDB detach the child.
|
|
gdb_test "set detach-on-fork on"
|
|
gdb_test "print unblock_parent = 1" " = 1"
|
|
} elseif { $resolution_method == "schedule-multiple" } {
|
|
# Make GDB resume both inferiors. The parent is blocked while the
|
|
# children executes, so the continue will make the child reach the
|
|
# end.
|
|
gdb_test "set schedule-multiple on"
|
|
gdb_test "continue" "$::inferior_exited_re normally.*" \
|
|
"continue to end of inferior 2"
|
|
gdb_test "inferior 1" ".*Switching to inferior 1.*"
|
|
gdb_test "print unblock_parent = 1" " = 1"
|
|
} else {
|
|
error "invalid resolution method: $resolution_method"
|
|
}
|
|
|
|
# Continue from the vfork call to the breakpoint.
|
|
gdb_test "continue" "Breakpoint $::decimal, break_parent .*" \
|
|
"continue to break_parent"
|
|
}
|
|
|
|
foreach_with_prefix resolution_method {detach-on-fork schedule-multiple} {
|
|
do_test $resolution_method
|
|
}
|