old-cross-binutils/gdb/testsuite/gdb.base/multi-forks.exp
Pedro Alves 2277426b30 gdb/
2009-07-02  Pedro Alves  <pedro@codesourcery.com>

	* linux-nat.c (linux_child_follow_fork): If we're staying attached
	to the child process, enable event reporting on it.  Don't handle
	checkpoints here.  Instead, add the child fork to the lwp thread
	and inferior lists without clobbering the previous inferior.  Let
	the thread_db layer learn about a new child process, even if
	following the parent.
	(linux_nat_switch_fork): Delete lwps of the current inferior only,
	instead of clearing the whole list.  Use thread_change_ptid to
	give the core the illusion the new checkpoint is still the same
	inferior.  Clear the register cache.
	(linux_handle_extended_wait): Handle checkpoints here.
	(linux_multi_process): Turn on.
	* linux-fork.c (struct fork_info) <pc>: Remove field.
	(init_fork_list): Do not delete the checkpoint from the inferior
	list (it is not there).
	(fork_load_infrun_state): Don't switch inferior_ptid here.  Pass
	the new checkpoint's ptid to linux_nat_switch_fork.
	(fork_save_infrun_state): Make static.  Don't stop the pc field of
	fork_info, it's gone.
	(linux_fork_mourn_inferior): Don't delete the checkpoint from the
	inferior list, it's not there.
	(linux_fork_detach): Ditto.
	(delete_fork_command): Replace mention of fork/checkpoint by
	checkpoint only.
	(detach_fork_command): Likewise.  Don't delete the checkpoint from
	the inferior list.
	(info_forks_command): Adjust.
	(restore_detach_fork): Delete.
	(checkpointing_pid): New.
	(linux_fork_checkpointing_p): New.
	(save_detach_fork): Delete.
	(checkpoint_command): Delete temp_detach_fork.  Don't remove
	breakpoints, that's a nop.  Store the pid of the process we're
	checkpointing, and use make_cleanup_restore_integer to restore it.
	Don't reinsert breakpoints here.
	(process_command, fork_command): Delete.
	(restart_command): Update comments to only mention checkpoints,
	not forks.
	(_initialize_linux_fork): Delete "fork", "process", "info forks"
	commands.
	* linux-fork.h (fork_save_infrun_state, fork_list): Delete
	declarations.
	(linux_fork_checkpointing_p): Declare.
	* cli/cli-cmds.c (killlist): New.
	* cli/cli-cmds.h (killlist): Declare.
	* gdbcmd.h (killlist): Declare.
	* inferior.c: Include "gdbthread.h".
	(detach_inferior_command, kill_inferior_command)
	(inferior_command): New.
	(info_inferiors_command): Allow specifying a specific inferior id.
	(_initialize_inferiors): Register "inferior", "kill inferior" and
	"detach inferior" commands.
	* infcmd.c (_initialize_infcmd): Make "kill" a prefix command.
	* gdbthread.h (any_thread_of_process): Declare.
	* thread.c (any_thread_of_process): New.

	* NEWS: Mention multi-inferior debugging.  Mention 'info
	inferiors', 'inferior', 'detach inferior' and 'kill inferior' as
	new commands.
	(Removed commands): New section, mentioning that 'info forks',
	'fork', 'process', 'delete fork' and 'detach fork' are now gone.

gdb/testsuite/
2009-07-02  Pedro Alves  <pedro@codesourcery.com>

	* gdb.base/multi-forks.exp: Only run detach-on-fork tests on
	linux.  Adjust to use "inferior", "info inferiors", "detach
	inferior" and "kill inferior" instead of "restart", "info fork",
	"detach fork" and "delete fork".
	* gdb.base/ending-run.exp: Spell out "info".
	* gdb.base/help.exp: Adjust to use test_prefix_command_help for
	the "kill" command.

gdb/doc/
2009-07-02  Pedro Alves  <pedro@codesourcery.com>

	* gdb.texinfo (Debugging multiple inferiors): Document the
	"inferior", "detach inferior" and "kill inferior" commands.
	(Debugging Programs with Multiple Processes): Adjust to mention
	generic "inferior" commands.  Delete mention of "detach fork" and
	"delete fork".  Cross reference to "Debugging multiple inferiors"
	section.
2009-07-02 21:57:28 +00:00

223 lines
6.9 KiB
Text

# Copyright 2005, 2006, 2007, 2008, 2009 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/>.
if $tracelevel then {
strace $tracelevel
}
if { [is_remote target] || ![isnative] } then {
continue
}
# Until "set follow-fork-mode" and "catch fork" are implemented on
# other targets...
#
if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-*-linux*"]} then {
continue
}
set prms_id 0
set bug_id 0
set testfile "multi-forks"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
untested multi-forks.exp
return -1
}
# Start with a fresh gdb
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
global gdb_prompt
# This is a test of gdb's ability to follow the parent, child or both
# parent and child of multiple Unix fork() system calls.
set exit_bp_loc [gdb_get_line_number "Set exit breakpoint here."]
# Insert a breakpoint at the location provided by the exit_bp_loc global
# and resume the execution until hitting that breakpoint. We also make
# sure to consume all the expected output from all processes as well,
# to make sure it doesn't cause trouble during a subsequent test.
proc continue_to_exit_bp_loc {} {
global exit_bp_loc decimal gdb_prompt
gdb_breakpoint $exit_bp_loc
send_gdb "continue\n"
# The output from the child processes can be interleaved arbitrarily
# with the output from GDB and the parent process. If we don't
# consume it all now, it can confuse later interactions.
set seen_done 0
set seen_break 0
set seen_prompt 0
set seen_timeout 0
while { ($seen_done < 16 || ! $seen_prompt) && ! $seen_timeout } {
# We don't know what order the interesting things will arrive in.
# Using a pattern of the form 'x|y|z' instead of -re x ... -re y
# ... -re z ensures that expect always chooses the match that
# occurs leftmost in the input, and not the pattern appearing
# first in the script that occurs anywhere in the input, so that
# we don't skip anything.
gdb_expect {
-re "($decimal done)|(Breakpoint)|($gdb_prompt)" {
if {[info exists expect_out(1,string)]} {
incr seen_done
} elseif {[info exists expect_out(2,string)]} {
set seen_break 1
} elseif {[info exists expect_out(3,string)]} {
set seen_prompt 1
}
array unset expect_out
}
timeout { set seen_timeout 1 }
}
}
if { $seen_timeout } {
fail "run to exit 2 (timeout)"
} elseif { ! $seen_prompt } {
fail "run to exit 2 (no prompt)"
} elseif { ! $seen_break } {
fail "run to exit 2 (no breakpoint hit)"
} elseif { $seen_done != 16 } {
fail "run to exit 2 (missing done messages)"
} else {
pass "run to exit 2"
}
}
# The inferior program builds a tree of processes by executing a loop
# four times, calling fork at each iteration. Thus, at each
# iteration, the total number of processes doubles; after four
# iterations, we have 16 processes. Each process saves the results
# from its 'fork' calls, so we can tell which leaf a given process is
# by looking at which forks returned zero and which returned a pid: a
# zero means to take the child's branch; a pid means to take the
# parent's branch.
# First set gdb to follow the child.
# The result should be that each of the 4 forks returns zero.
runto_main
gdb_test "set follow child"
continue_to_exit_bp_loc
gdb_test "print pids" "\\$.* = \\{0, 0, 0, 0\\}.*" "follow child, print pids"
# Now set gdb to follow the parent.
# Result should be that none of the 4 forks returns zero.
runto_main
gdb_test "set follow parent" "" ""
continue_to_exit_bp_loc
gdb_test "print pids\[0\]==0 || pids\[1\]==0 || pids\[2\]==0 || pids\[3\]==0" \
" = 0" "follow parent, print pids"
#
# Now test with detach-on-fork off.
#
# detach-on-fork isn't implemented on hpux.
#
if {![istarget "*-*-linux*"]} then {
continue
}
# Start with a fresh gdb
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
runto_main
gdb_breakpoint $exit_bp_loc
gdb_test "help set detach-on-fork" "whether gdb will detach the child.*" \
"help set detach"
gdb_test "show detach-on-fork" "on." "show detach default on"
gdb_test "set detach off" "" "set detach off"
#
# We will now run every fork up to the exit bp,
# eventually winding up with 16 inferiors.
#
for {set i 1} {$i <= 15} {incr i} {
gdb_test "continue" "Breakpoint .* main .*exit.*" "Run to exit $i"
gdb_test "info inferior" " 5 .* 4 .* 3 .* 2 .*" "info inferior $i"
gdb_test "inferior $i + 1" "(_dl_sysinfo_int80|fork|__kernel_(v|)syscall).*" \
"inferior $i"
}
gdb_test "continue" "Breakpoint .* main .*exit.*" "Run to exit 16"
gdb_test "info inferiors" " 5 .* 4 .* 3 .* 2 .*" "info inferior 16"
gdb_test "inferior 2" " main .*" "restart final"
#
# Now we should examine all the pids.
#
#
# Test detach inferior
#
# [assumes we're at #1]
gdb_test "detach inferior 2" "Detaching .*" "Detach 2"
gdb_test "detach inferior 3" "Detaching .*" "Detach 3"
gdb_test "detach inferior 4" "Detaching .*" "Detach 4"
gdb_test "detach inferior 5" "Detaching .*" "Detach 5"
#
# Test kill inferior
#
gdb_test "kill inferior 6" "" "Kill 6"
gdb_test "info inferior 6" "Inferior ID 6 not known." "Did kill 6"
gdb_test "kill inferior 7" "" "Kill 7"
gdb_test "info inferior 7" "Inferior ID 7 not known." "Did kill 7"
gdb_test "kill inferior 8" "" "Kill 8"
gdb_test "info inferior 8" "Inferior ID 8 not known." "Did kill 8"
gdb_test "kill inferior 9" "" "Kill 9"
gdb_test "info inferior 9" "Inferior ID 9 not known." "Did kill 9"
gdb_test "kill inferior 10" "" "Kill 10"
gdb_test "info inferior 10" "Inferior ID 10 not known." "Did kill 10"
gdb_test "kill inferior 11" "" "Kill 11"
gdb_test "info inferior 11" "Inferior ID 11 not known." "Did kill 11"
gdb_test "kill inferior 12" "" "Kill 12"
gdb_test "info inferior 12" "Inferior ID 12 not known." "Did kill 12"
gdb_test "kill inferior 13" "" "Kill 13"
gdb_test "info inferior 13" "Inferior ID 13 not known." "Did kill 13"
gdb_test "kill inferior 14" "" "Kill 14"
gdb_test "info inferior 14" "Inferior ID 14 not known." "Did kill 14"
gdb_test "kill inferior 15" "" "Kill 15"
gdb_test "info inferior 15" "Inferior ID 15 not known." "Did kill 15"
gdb_test "kill inferior 16" "" "Kill 16"
gdb_test "info inferior 16" "Inferior ID 16 not known." "Did kill 16"
return 0