aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.threads/attach-non-stop.exp
blob: eb12e6bbda18bbc08e485348f3fcd9423d063a43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Copyright 2021-2024 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 attaching to a multi-threaded process, in all combinations of:
#
#  - set non-stop on/off
#  - maint target non-stop off/on
#  - "attach" vs "attach &"

require can_spawn_for_attach

standard_testfile

# The test proper.  See description above.

proc test {target_non_stop non_stop cmd} {
    global binfile srcfile
    global gdb_prompt
    global decimal
    global GDBFLAGS

    # Number of threads started by the program.
    set n_threads 10

    save_vars { GDBFLAGS } {
	append GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\""
	append GDBFLAGS " -ex \"set non-stop $non_stop\""
	clean_restart $binfile
    }

    set test_spawn_id [spawn_wait_for_attach $binfile]
    set testpid [spawn_id_get_pid $test_spawn_id]

    set attached 0
    set test "attach"
    set any "\[^\r\n\]*"

    if {$cmd == "attach"} {
	gdb_test_multiple "attach $testpid" $test {
	    -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " {
		pass $test
		set attached 1
	    }
	}

	if {!$attached} {
	    kill_wait_spawned_process $test_spawn_id
	    return
	}

	if {$non_stop} {
	    # In non-stop, we will see one stop per thread after
	    # the prompt.
	    set stops 0
	    set test "seen all stops"
	    for {set thread 1} { $thread <= $n_threads } { incr thread } {
		gdb_test_multiple "" $test {
		    -re "Thread $::decimal ${any} stopped" {
			incr stops
		    }
		}
	    }

	    # If we haven't seen all stops, then the gdb_test_multiple
	    # in the loop above will have already issued a FAIL.
	    if {$stops == $n_threads} {
		pass $test
	    }
	}

	gdb_test_multiple "info threads" "" {
	    -re "\\(running\\).*$gdb_prompt $" {
		fail $gdb_test_name
	    }
	    -re "$gdb_prompt $" {
		pass $gdb_test_name
	    }
	}
    } else {
	gdb_test_multiple "attach $testpid &" $test {
	    -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " {
		pass $test
		set attached 1
	    }
	}

	if {!$attached} {
	    kill_wait_spawned_process $test_spawn_id
	    return
	}

	set running_count 0
	gdb_test_multiple "info threads" "all threads running" {
	    -re "\\(running\\)" {
		incr running_count
		exp_continue
	    }
	    -re "Cannot execute this command while the target is running.*$gdb_prompt $" {
		# Testing against a remote server that doesn't do
		# non-stop mode.  Explicitly interrupt.  This doesn't
		# test the same code paths in GDB, but it's still
		# something.
		gdb_test_multiple "interrupt" "" {
		    -re "$gdb_prompt " {
			gdb_test_multiple "" $gdb_test_name {
			    -re "received signal SIGINT, Interrupt" {
				pass $gdb_test_name
			    }
			}
		    }
		}
	    }
	    -re "$gdb_prompt $" {
		gdb_assert {$running_count == ($n_threads + 1)} $gdb_test_name
	    }
	}
    }

    gdb_test "detach" "Detaching from.*"

    kill_wait_spawned_process $test_spawn_id
}

if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1} {
    return -1
}

foreach_with_prefix target-non-stop {"off" "on"} {
    foreach_with_prefix non-stop {"off" "on"} {
	foreach_with_prefix cmd {"attach" "attach&"} {
	    test ${target-non-stop} ${non-stop} ${cmd}
	}
    }
}