1# Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 2# Free Software Foundation, Inc. 3 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17if $tracelevel then { 18 strace $tracelevel 19 } 20 21if { [is_remote target] || ![isnative] } then { 22 continue 23} 24 25# Until "set follow-fork-mode" and "catch fork" are implemented on 26# other targets... 27# 28if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-*-linux*"]} then { 29 continue 30} 31 32 33set testfile "multi-forks" 34set srcfile ${testfile}.c 35set binfile ${objdir}/${subdir}/${testfile} 36 37if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { 38 untested multi-forks.exp 39 return -1 40} 41 42# Start with a fresh gdb 43 44gdb_exit 45gdb_start 46gdb_reinitialize_dir $srcdir/$subdir 47gdb_load ${binfile} 48 49global gdb_prompt 50 51# This is a test of gdb's ability to follow the parent, child or both 52# parent and child of multiple Unix fork() system calls. 53 54set exit_bp_loc [gdb_get_line_number "Set exit breakpoint here."] 55 56# Insert a breakpoint at the location provided by the exit_bp_loc global 57# and resume the execution until hitting that breakpoint. We also make 58# sure to consume all the expected output from all processes as well, 59# to make sure it doesn't cause trouble during a subsequent test. 60 61proc continue_to_exit_bp_loc {} { 62 global exit_bp_loc decimal gdb_prompt 63 64 gdb_breakpoint $exit_bp_loc 65 66 send_gdb "continue\n" 67 68 # The output from the child processes can be interleaved arbitrarily 69 # with the output from GDB and the parent process. If we don't 70 # consume it all now, it can confuse later interactions. 71 set seen_done 0 72 set seen_break 0 73 set seen_prompt 0 74 set seen_timeout 0 75 while { ($seen_done < 16 || ! $seen_prompt) && ! $seen_timeout } { 76 # We don't know what order the interesting things will arrive in. 77 # Using a pattern of the form 'x|y|z' instead of -re x ... -re y 78 # ... -re z ensures that expect always chooses the match that 79 # occurs leftmost in the input, and not the pattern appearing 80 # first in the script that occurs anywhere in the input, so that 81 # we don't skip anything. 82 gdb_expect { 83 -re "($decimal done)|(Breakpoint)|($gdb_prompt)" { 84 if {[info exists expect_out(1,string)]} { 85 incr seen_done 86 } elseif {[info exists expect_out(2,string)]} { 87 set seen_break 1 88 } elseif {[info exists expect_out(3,string)]} { 89 set seen_prompt 1 90 } 91 array unset expect_out 92 } 93 timeout { set seen_timeout 1 } 94 } 95 } 96 97 if { $seen_timeout } { 98 fail "run to exit 2 (timeout)" 99 } elseif { ! $seen_prompt } { 100 fail "run to exit 2 (no prompt)" 101 } elseif { ! $seen_break } { 102 fail "run to exit 2 (no breakpoint hit)" 103 } elseif { $seen_done != 16 } { 104 fail "run to exit 2 (missing done messages)" 105 } else { 106 pass "run to exit 2" 107 } 108} 109 110# The inferior program builds a tree of processes by executing a loop 111# four times, calling fork at each iteration. Thus, at each 112# iteration, the total number of processes doubles; after four 113# iterations, we have 16 processes. Each process saves the results 114# from its 'fork' calls, so we can tell which leaf a given process is 115# by looking at which forks returned zero and which returned a pid: a 116# zero means to take the child's branch; a pid means to take the 117# parent's branch. 118 119# First set gdb to follow the child. 120# The result should be that each of the 4 forks returns zero. 121 122runto_main 123gdb_test_no_output "set follow-fork child" 124continue_to_exit_bp_loc 125 126gdb_test "print pids" "\\$.* = \\{0, 0, 0, 0\\}.*" "follow child, print pids" 127 128# Now set gdb to follow the parent. 129# Result should be that none of the 4 forks returns zero. 130 131runto_main 132gdb_test_no_output "set follow-fork parent" "" 133continue_to_exit_bp_loc 134 135gdb_test "print pids\[0\]==0 || pids\[1\]==0 || pids\[2\]==0 || pids\[3\]==0" \ 136 " = 0" "follow parent, print pids" 137 138# 139# Now test with detach-on-fork off. 140# 141 142# detach-on-fork isn't implemented on hpux. 143# 144if {![istarget "*-*-linux*"]} then { 145 continue 146} 147 148# Start with a fresh gdb 149 150gdb_exit 151gdb_start 152gdb_reinitialize_dir $srcdir/$subdir 153gdb_load ${binfile} 154 155runto_main 156gdb_breakpoint $exit_bp_loc 157 158gdb_test "help set detach-on-fork" "whether gdb will detach the child.*" \ 159 "help set detach" 160 161gdb_test "show detach-on-fork" "on." "show detach default on" 162 163gdb_test_no_output "set detach off" "set detach off" 164 165# 166# We will now run every fork up to the exit bp, 167# eventually winding up with 16 inferiors. 168# 169 170for {set i 1} {$i <= 15} {incr i} { 171 gdb_test "continue" "Breakpoint .* main .*exit.*" "Run to exit $i" 172 gdb_test "info inferior" " 5 .* 4 .* 3 .* 2 .*" "info inferior $i" 173 gdb_test "inferior $i + 1" "(_dl_sysinfo_int80|fork|__kernel_(v|)syscall).*" \ 174 "inferior $i" 175} 176 177gdb_test "continue" "Breakpoint .* main .*exit.*" "Run to exit 16" 178gdb_test "info inferiors" " 5 .* 4 .* 3 .* 2 .*" "info inferior 16" 179gdb_test "inferior 2" " main .*" "restart final" 180 181# 182# Now we should examine all the pids. 183# 184 185# 186# Test detach inferior 187# 188 189# [assumes we're at #1] 190gdb_test "detach inferior 2" "Detaching .*" "Detach 2" 191gdb_test "detach inferior 3" "Detaching .*" "Detach 3" 192gdb_test "detach inferior 4" "Detaching .*" "Detach 4" 193gdb_test "detach inferior 5" "Detaching .*" "Detach 5" 194 195# 196# Test kill inferior 197# 198 199gdb_test_no_output "kill inferior 6" "Kill 6" 200gdb_test "info inferior 6" "<null>.*" "Did kill 6" 201gdb_test_no_output "kill inferior 7" "Kill 7" 202gdb_test "info inferior 7" "<null>.*" "Did kill 7" 203gdb_test_no_output "kill inferior 8" "Kill 8" 204gdb_test "info inferior 8" "<null>.*" "Did kill 8" 205gdb_test_no_output "kill inferior 9" "Kill 9" 206gdb_test "info inferior 9" "<null>.*" "Did kill 9" 207gdb_test_no_output "kill inferior 10" "Kill 10" 208gdb_test "info inferior 10" "<null>.*" "Did kill 10" 209gdb_test_no_output "kill inferior 11" "Kill 11" 210gdb_test "info inferior 11" "<null>.*" "Did kill 11" 211gdb_test_no_output "kill inferior 12" "Kill 12" 212gdb_test "info inferior 12" "<null>.*" "Did kill 12" 213gdb_test_no_output "kill inferior 13" "Kill 13" 214gdb_test "info inferior 13" "<null>.*" "Did kill 13" 215gdb_test_no_output "kill inferior 14" "Kill 14" 216gdb_test "info inferior 14" "<null>.*" "Did kill 14" 217gdb_test_no_output "kill inferior 15" "Kill 15" 218gdb_test "info inferior 15" "<null>.*" "Did kill 15" 219gdb_test_no_output "kill inferior 16" "Kill 16" 220gdb_test "info inferior 16" "<null>.*" "Did kill 16" 221 222return 0 223