[gdb/syscalls] Sync with strace v6.13
[binutils-gdb.git] / gdb / testsuite / gdb.base / kill-during-detach.exp
blob68292cc3c51cae0c4d428599f1510d7d2759c586
1 # Copyright 2023-2024 Free Software Foundation, Inc.
2 # This program is free software; you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation; either version 3 of the License, or
5 # (at your option) any later version.
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 # GNU General Public License for more details.
12 # You should have received a copy of the GNU General Public License
13 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 # This test checks that GDB correctly handles several cases that can
16 # occur when GDB attempts to detach an inferior process.  The process
17 # can exit or be terminated (e.g.  via SIGKILL) prior to GDB's event
18 # loop getting a chance to remove it from GDB's internal data
19 # structures.  To complicate things even more, detach works differently
20 # when a checkpoint (created via GDB's "checkpoint" command) exists for
21 # the inferior.  This test checks all four possibilities: process exit
22 # with no checkpoint, process termination with no checkpoint, process
23 # exit with a checkpoint, and process termination with a checkpoint.
25 standard_testfile
27 # This test requires python.
28 require allow_python_tests
30 # This test attempts to kill a process on the host running GDB, so
31 # disallow remote targets.  (Setting --target_board to
32 # native-gdbserver or native-extended-gdbserver should still work.)
33 require {!is_remote target}
35 # Checkpoint support only works on native Linux:
36 if { [istarget "*-*-linux*"] && [target_info gdb_protocol] == ""} {
37     set has_checkpoint true
38 } else {
39     set has_checkpoint false
42 set flags {}
43 lappend flags debug
44 lappend flags additional_flags=-DBINFILE=$binfile
46 if {[build_executable "failed to prepare" $testfile $srcfile $flags] == -1} {
47     return -1
50 set checkpoint_line [gdb_get_line_number "Checkpoint here"]
52 # Start an inferior, which blocks in a spin loop.  Setup a Python
53 # function that performs an action based on EXIT_P that will cause the
54 # inferior to exit, and then, within the same Python function, ask GDB
55 # to detach from the inferior.  Use 'continue&' to run the inferior in
56 # the background, and then invoke the Python function.  Note, too, that
57 # non-stop mode is enabled during the restart; if this is not done,
58 # remote_target::putpkt_binary in remote.c will disallow some of the
59 # operations necessary for this test.
61 # The idea is that GDB's event loop will not get a chance to handle
62 # the inferior exiting, so it will only be at the point that we try to
63 # detach that we notice that the inferior has exited.
65 # When EXIT_P is true the action we perform to terminate the inferior
66 # is to set a flag in the inferior, which allows the inferior to break
67 # out of its spin loop.
69 # When EXIT_P is false the action we perform is to send SIGKILL to the
70 # inferior.
72 # When CHECKPOINT_P is true, before issuing 'continue&' we use the
73 # 'checkpoint' command to create a checkpoint of GDB.
75 # When CHECKPOINT_P is false we don't use the 'checkpoint' command.
76 proc run_test { exit_p checkpoint_p } {
77     save_vars { ::GDBFLAGS } {
78         append ::GDBFLAGS " -ex \"set non-stop on\""
79         clean_restart $::binfile
80     }
82     if {![runto_main]} {
83         return -1
84     }
86     if { $checkpoint_p } {
87         # Active checkpoint-specific code in $srcfile.
88         gdb_test_no_output "set var with_checkpoint=1"
90         # Run to line where we want to set the checkpoint.
91         gdb_breakpoint "$::srcfile:$::checkpoint_line"
92         gdb_continue_to_breakpoint "checkpoint line"
94         # Set the checkpoint.
95         gdb_test "checkpoint" \
96             "checkpoint 1: fork returned pid $::decimal\\."
97     }
99     # Must get the PID before we resume the inferior.
100     set inf_pid [get_inferior_pid]
102     # Put the PID in a python variable so that a numerical PID won't
103     # appear in the PASS/FAIL output.
104     gdb_test_no_output "python inf_pid=$inf_pid" "assign inf_pid"
106     gdb_test "continue &"
108     if { $exit_p } {
109         set action_line "gdb.execute(\"set variable dont_exit_just_yet=0\")"
110     } else {
111         set action_line "os.kill(inf_pid, signal.SIGKILL)"
112     }
114     gdb_test_multiline "Create worker function" \
115         "python" "" \
116         "import time" "" \
117         "import os" "" \
118         "import signal" "" \
119         "def kill_and_detach():" "" \
120         "   $action_line" "" \
121         "   time.sleep(1)" "" \
122         "   gdb.execute(\"detach\")" "" \
123         "end" ""
125     if { $checkpoint_p } {
126         # NOTE: The 'checkpoint' system in GDB appears to be a little
127         # iffy.  This detach does seem to restore the checkpoint, but
128         # it leaves the inferior stuck in a running state.
129         gdb_test_no_output "python kill_and_detach()"
130     } else {
131         gdb_test "python kill_and_detach()" \
132             "\\\[Inferior $::decimal \[^\r\n\]+ detached\\\]"
133     }
136 if { $has_checkpoint } {
137     set checkpoint_iters { true false }
138 } else {
139     set checkpoint_iters { false }
142 foreach_with_prefix exit_p { true false } {
143     foreach_with_prefix checkpoint_p $checkpoint_iters {
144         run_test $exit_p $checkpoint_p
145     }