1# Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# This test is based on gdb.base/attach.exp with modifications by Jeff Johnston
17# <jjohnstn@redhat.com> and Jan Kratochvil <jan.kratochvil@redhat.com>.
18
19# This test only works on Linux
20if { ![isnative] || [is_remote host] || ![istarget *-linux*] } {
21    continue
22}
23
24set testfile "attachstop-mt"
25set srcfile  ${testfile}.c
26set binfile  ${objdir}/${subdir}/${testfile}
27set escapedbinfile  [string_to_regexp ${objdir}/${subdir}/${testfile}]
28
29#execute_anywhere "rm -f ${binfile}"
30remote_exec build "rm -f ${binfile}"
31# For debugging this test
32#
33#log_user 1
34
35# build the test case
36#
37if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
38    untested attachstop-mt.exp
39    return -1
40}
41
42if [get_compiler_info ${binfile}] {
43    return -1
44}
45
46# Start the program running and then wait for a bit, to be sure
47# that it can be attached to.
48
49set testpid [eval exec $binfile &]
50
51# No race
52sleep 2
53
54# The testcase has three threads, find some other thread TID for $testpid2.
55set tids [exec sh -c "echo /proc/$testpid/task/*"]
56regsub -all /proc/$testpid/task/ $tids {} tids
57if {$tids == "*"} {
58    unresolved "/proc/PID/task is not supported (kernel-2.4?)"
59    remote_exec build "kill -9 ${testpid}"
60    return -1
61}
62set tids [lsort -integer [split $tids]]
63if {[llength $tids] != 3 || [lindex $tids 0] != $testpid} {
64    verbose -log "Invalid TIDs <$tids> for PID $testpid"
65    fail "Invalid TIDs found"
66    remote_exec build "kill -9 ${testpid}"
67    return -1
68}
69set testpid2 [lindex $tids 2]
70
71# Initial sanity test it is normally sleeping
72set status2 /proc/${testpid}/task/${testpid2}/status
73set fileid0 [open $status2 r];
74gets $fileid0 line1;
75gets $fileid0 line2;
76close $fileid0;
77
78set test "attach0, initial sanity check of the sleeping state"
79if {[string match "*(sleeping)*" $line2]} {
80  pass $test
81} else {
82  fail $test
83}
84
85# Sttach and detach to test it will not become stopped
86gdb_start
87gdb_reinitialize_dir $srcdir/$subdir
88gdb_load ${binfile}
89
90set test "attach0 to sleeping"
91gdb_test_multiple "attach $testpid" "$test" {
92    -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
93        pass "$test"
94    }
95}
96
97gdb_test "gcore /dev/null" ".*aved corefile.*" "attach0 to sleeping gcore invocation"
98
99gdb_test "thread 2" ".*witching to thread 2 .*" "attach0 to sleeping switch thread"
100
101gdb_test "bt" ".*sleep.*func.*" "attach0 to sleeping bt"
102
103# Exit and detach the process.
104
105gdb_exit
106
107# No race
108sleep 2
109
110# Check it did not get stopped by our gdb
111set fileid1 [open $status2 r];
112gets $fileid1 line1;
113gets $fileid1 line2;
114close $fileid1;
115
116set test "attach1, post-gdb sanity check of the sleeping state - Red Hat BZ 197584"
117if {[string match "*(sleeping)*" $line2]} {
118  pass $test
119} else {
120  fail $test
121}
122
123# Stop the program
124remote_exec build "kill -s STOP ${testpid}"
125
126# No race
127sleep 2
128
129# Check it really got stopped by kill(1)
130set fileid2 [open $status2 r];
131gets $fileid2 line1;
132gets $fileid2 line2;
133close $fileid2;
134
135set test "attach2, initial sanity check of the stopped state"
136if {[string match "*(stopped)*" $line2]} {
137  pass $test
138} else {
139  fail $test
140}
141
142# Start with clean gdb
143gdb_start
144gdb_reinitialize_dir $srcdir/$subdir
145gdb_load ${binfile}
146
147# Verify that we can attach to the process by first giving its
148# executable name via the file command, and using attach with the
149# process ID.
150
151set test "set file, before attach3 to stopped process"
152gdb_test_multiple "file $binfile" "$test" {
153   -re "Load new symbol table from.*y or n. $" {
154        gdb_test "y" "Reading symbols from $escapedbinfile\.\.\.*done." \
155		"$test (re-read)"
156    }
157    -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $" {
158        pass "$test"
159    }
160}
161
162set test "attach3 to stopped, after setting file"
163gdb_test_multiple "attach $testpid" "$test" {
164    -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
165        pass "$test"
166    }
167}
168
169# We may be already after the threads phase.
170# `thread 2' command is important for the test to switch the current thread to
171# a non-primary one for the detach process.
172
173gdb_test "thread 2" ".*(witching to thread 2 |hread ID 2 not known).*" "attach3 to stopped switch thread"
174gdb_test "bt" ".*sleep.*(func|main).*" "attach3 to stopped bt"
175
176# Exit and detach the process.
177gdb_exit
178
179# Stop the program
180remote_exec build "kill -s STOP ${testpid}"
181
182# No race
183sleep 2
184
185# Continue the test as we would hit another expected bug regarding
186# 	Program received signal SIGSTOP, Stopped (signal).
187# across NPTL threads.
188
189gdb_start
190gdb_reinitialize_dir $srcdir/$subdir
191gdb_load ${binfile}
192
193# Verify that we can attach to the process just by giving the
194# process ID.
195
196set test "attach4 to stopped, after setting file"
197gdb_test_multiple "attach $testpid" "$test" {
198    -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
199        pass "$test"
200    }
201}
202
203# We may be already after the threads phase.
204# `thread 2' command is important for the test to switch the current thread to
205# a non-primary one for the detach process.
206
207gdb_test "thread 2" ".*(witching to thread 2 |hread ID 2 not known).*" "attach4 to stopped switch thread"
208gdb_test "bt" ".*sleep.*(func|main).*" "attach4 to stopped bt"
209
210# RHEL3U8 kernel-2.4.21-47.EL will not return SIGINT but only shorten the sleep.
211gdb_breakpoint [gdb_get_line_number "Ridiculous time"]
212gdb_breakpoint [gdb_get_line_number "cut the sleep time"]
213set test "attach4 continue"
214gdb_test_multiple "continue" "continue ($test)" {
215    -re "Continuing" {
216	pass "continue ($test)"
217    }
218}
219
220# For this to work we must be sure to consume the "Continuing."
221# message first, or GDB's signal handler may not be in place.
222after 1000 {send_gdb "\003"}
223set test "attach4 stop by interrupt"
224gdb_expect {
225  -re "Program received signal SIGINT.*$gdb_prompt $"
226    {
227      pass $test
228    }
229  -re "Breakpoint \[0-9\].*$srcfile.*$gdb_prompt $"
230    {
231      pass $test
232    }
233  timeout
234    {
235      fail "$test (timeout)"
236    }
237}
238
239gdb_exit
240
241# No race
242sleep 2
243
244# At this point, the process should be sleeping
245
246set fileid4 [open $status2 r];
247gets $fileid4 line1;
248gets $fileid4 line2;
249close $fileid4;
250
251set test "attach4, exit leaves process sleeping"
252if {[string match "*(sleeping)*" $line2]} {
253  pass $test
254} else {
255  fail $test
256}
257
258# Make sure we don't leave a process around to confuse
259# the next test run (and prevent the compile by keeping
260# the text file busy), in case the "set should_exit" didn't
261# work.
262
263remote_exec build "kill -9 ${testpid}"
264
265return 0
266