[PATCH v3 3/4] Extended-remote support for exec event tests

Don Breazeal
2015-09-09T23:06:29Z

Hi Pedro,

This updated patch addresses issues raised in the review of the
previous version, as outlined below. It also includes the following:

* gdb.base/foll-exec.exp: Copyright, formatting, and error handling
changes that had been requested for follow-exec-mode.exp here:
https://sourceware.org/ml/gdb-patches/2015-08/msg00753.html, since
that test had been derived from this one, which contained most of
the same issues.

* gdb.base/foll-vfork.exp: Enabled exec-related tests that had been
disabled with the implementation of extended-remote vfork event
support.

On 8/13/2015 8:22 AM, Pedro Alves wrote:
> On 07/31/2015 12:19 AM, Don Breazeal wrote:
>
>> This patch updates several exec-related tests and some of the
>> library functions in order to get them running with extended-remote.
>> There were three changes that were required, as follows:
>>
>> In gdb.base/foll-exec.exp, the proc 'zap_session' is used repeatedly
>> to reset the state of the debugger before the next test. Part of
>> that procedure is to 'set exec-file'. For remote targets, it is
>> necessary to also 'set remote exec-file' to achieve the same
>> effect (and execute the correct binary file in the subsequent test).
>
> This assumes local gdbserver testing. This is something that
> should be done in the target board. Look for exec-file in
> gdb/testsuite/boards/native-extended-gdbserver.exp.
> Maybe we should just clean_restart instead ?

Eliminated proc zap_session and used clean_restart instead.

>
>>
>> In gdb.base/pie-execl.exp, there is an expect statement with an
>> expression that is used to match output from both gdb and the
>> program under debug. For the remote target, this had to be
>> split into two expressions, using $inferior_spawn_id to match
>> the output from the program.
>>
>> Because I had encountered problems with extended-remote exec events
>> in non-stop mode in my manual testing, I added non-stop testing to
>> the non-ldr-exc-[1234].exp tests. In order to set non-stop mode
>> for remote targets, it is necessary to 'set non-stop on' after gdb
>> has started, but before it connects to gdbserver. The non-ldr-...
>> tests call 'clean_restart' in between tests, and it eventually calls
>> 'gdb_start' which starts gdb and gdbserver and connects them. By
>> adding a stop mode argument to clean_restart and gdb_start (in
>> both lib/gdb.exp and boards/native-extended-gdbserver.exp), it was
>> possible to set non-stop mode for remote targets. Since the
>> arguments have a default value "all-stop", and only have an effect
>> when "non-stop" is passed, these changes do not affect any existing
>> test behavior.
>
> I don't think we can do this, because gdb_start is an overridable
> function (see comment above it). You can instead append
> set non-stop on to GDBFLAGS. E.g.,:
>
> save_vars { GDBFLAGS } {
> append GDBFLAGS " -ex \"set non-stop $nonstop\""
> clean_restart
> }

Restored clean_restart, gdb_start, etc to their original implementations,
and used the save_vars approach above in gdb.threads/non-ldr-exc-[1234].exp.
Thanks.

>
>> diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
>> index 69e5cc6..147e7f3 100644
>> --- a/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
>> +++ b/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
>> @@ -28,11 +28,11 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
>> return -1
>> }
>>
>> -proc do_test { lock_sched } {
>> - with_test_prefix "lock-sched$lock_sched" {
>> +proc do_test { lock_sched stop_mode } {
>> + with_test_prefix "lock-sched$lock_sched,$stop_mode" {
>> global executable
>>
>> - clean_restart ${executable}
>> + clean_restart ${executable} $stop_mode
>>
>> if ![runto_main] {
>> return -1
>> @@ -48,11 +48,17 @@ proc do_test { lock_sched } {
>> gdb_test_no_output "set scheduler-locking on"
>> }
>>
>> + if { $stop_mode == "non-stop" } {
>> + gdb_test "thread 2" "Switching.*"
>> + }
>> +
>> gdb_test "continue" \
>> ".*is executing new program.*Breakpoint 1, main.* at .*" \
>> "continue over exec"
>> }
>> }
>>
>> -do_test 0
>> -do_test 1
>> +do_test 0 "all-stop"
>> +do_test 1 "all-stop"
>> +do_test 0 "non-stop"
>> +do_test 1 "non-stop"
>
> Please use foreach. E.g.,
>
> foreach nonstop {"on" "off"} {
> foreach schedlock {"on" "off"} {
> do_test ...
> }
> }
>
> Note that schedlock on has no effect in non-stop mode.
> Maybe if !lock_sched && nonstop, we could issue "continue -a"
> instead of continue.

I couldn't find any documentation of 'continue -a'. (?) I just used
a conditional to prevent running the lock_sched/nonstop tests.

foreach nonstop {"on" "off"} {
foreach schedlock {"on" "off"} {
if {$schedlock == "on" && $nonstop == "on"} {
# Schedule locking has no effect in nonstop mode.
continue
}
do_test $schedlock $nonstop
}
}

>
>> diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
>> index 9386153..748ff11 100644
>> --- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
>> +++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
>> @@ -29,18 +29,26 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
>> return -1
>> }
>>
>> -proc do_test { lock_sched } {
>> - with_test_prefix "lock-sched$lock_sched" {
>> +proc do_test { lock_sched stop_mode } {
>> + with_test_prefix "lock-sched$lock_sched,$stop_mode" {
>> global executable
>>
>> - clean_restart ${executable}
>> + clean_restart ${executable} $stop_mode
>>
>> if ![runto_main] {
>> return -1
>> }
>>
>> gdb_breakpoint [gdb_get_line_number "break-here"]
>> - gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> + gdb_test_multiple "continue" "continue to breakpoint" {
>> + -re ".*Breakpoint.*break-here.*" {
>
> This doesn't expect the prompt, which is going to be
> racy -- the following gdb_test may fail if this test manages
> to leave the prompt in the expect buffer. What motivated this change?

This was a leftover from a change that was reverted, sorry. This has
been restored to the original.

Thanks,
--Don

-----

This patch updates several exec-related tests and some of the
library functions in order to get them running with extended-remote.
There were three changes that were required, as follows:

In gdb.base/foll-exec.exp, use 'clean_start' in place of proc
'zap_session' to reset the state of the debugger between tests.
This sets 'remote exec-file' to execute the correct binary file
in each subsequent test.

In gdb.base/pie-execl.exp, there is an expect statement with an
expression that is used to match output from both gdb and the
program under debug. For the remote target, this had to be
split into two expressions, using $inferior_spawn_id to match
the output from the program.

Because I had encountered problems with extended-remote exec events
in non-stop mode in my manual testing, I added non-stop testing to
the non-ldr-exc-[1234].exp tests. In order to set non-stop mode
for remote targets, it is necessary to 'set non-stop on' after gdb
has started, but before it connects to gdbserver. This is done
using 'save_vars' to set non-stop mode in GDBFLAGS, so GDB sets
non-stop mode on startup.

Tested on x86_64 GNU/Linux with native, native-gdbserver, and
native-extended-gdbserver targets.

gdb/testsuite/
2015-09-09 Don Breazeal <donb@codesourcery.com>

* gdb.base/foll-exec.c: Add copyright header. Fix
formatting issues.
* gdb.base/foll-exec.exp (zap_session): Delete proc.
(do_exec_tests): Use clean_restart in place of zap_session,
and for test initialization. Fix formatting issues. Use
fail in place of perror.
* gdb.base/pie-execl.exp (main): Use 'inferior_spawn_id' in
an expect statement to match an expression with output from
the program under debug.
* gdb.threads/non-ldr-exc-1.exp (do_test, main): Add
non-stop tests and pass stop mode argument to clean_restart.
Use save_vars to enable non-stop in GDBFLAGS.
* gdb.threads/non-ldr-exc-2.exp: Likewise.
* gdb.threads/non-ldr-exc-3.exp: Likewise.
* gdb.threads/non-ldr-exc-4.exp: Likewise.

---
gdb/testsuite/gdb.base/foll-exec.c | 44 ++++++++++++-------
gdb/testsuite/gdb.base/foll-exec.exp | 65 +++++++----------------------
gdb/testsuite/gdb.base/foll-vfork.exp | 29 ++++++-------
gdb/testsuite/gdb.base/pie-execl.exp | 24 ++++++++++-
gdb/testsuite/gdb.threads/non-ldr-exc-1.exp | 24 ++++++++---
gdb/testsuite/gdb.threads/non-ldr-exc-2.exp | 24 ++++++++---
gdb/testsuite/gdb.threads/non-ldr-exc-3.exp | 30 ++++++++++---
gdb/testsuite/gdb.threads/non-ldr-exc-4.exp | 24 ++++++++---
8 files changed, 161 insertions(+), 103 deletions(-)

diff --git a/gdb/testsuite/gdb.base/foll-exec.c b/gdb/testsuite/gdb.base/foll-exec.c
index 6e302bb..77287a4 100644
--- a/gdb/testsuite/gdb.base/foll-exec.c
+++ b/gdb/testsuite/gdb.base/foll-exec.c
@@ -1,36 +1,52 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 1997-2015 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/>. */
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

-
-int global_i = 100;
+int global_i = 100;

int main (void)
{
- int local_j = global_i+1;
- int local_k = local_j+1;
+ int local_j = global_i + 1;
+ int local_k = local_j + 1;

printf ("foll-exec is about to execlp(execd-prog)...\n");

execlp (BASEDIR "/execd-prog",
- BASEDIR "/execd-prog",
- "execlp arg1 from foll-exec",
- (char *)0);
+ BASEDIR "/execd-prog",
+ "execlp arg1 from foll-exec",
+ (char *) 0);

printf ("foll-exec is about to execl(execd-prog)...\n");

execl (BASEDIR "/execd-prog", /* tbreak-execl */
- BASEDIR "/execd-prog",
- "execl arg1 from foll-exec",
- "execl arg2 from foll-exec",
- (char *)0);
+ BASEDIR "/execd-prog",
+ "execl arg1 from foll-exec",
+ "execl arg2 from foll-exec",
+ (char *) 0);

{
static char * argv[] = {
- (char *)BASEDIR "/execd-prog",
- (char *)"execv arg1 from foll-exec",
- (char *)0};
+ (char *) BASEDIR "/execd-prog",
+ (char *) "execv arg1 from foll-exec",
+ (char *) 0};

printf ("foll-exec is about to execv(execd-prog)...\n");

diff --git a/gdb/testsuite/gdb.base/foll-exec.exp b/gdb/testsuite/gdb.base/foll-exec.exp
index 5bea3ba..0a6347c 100644
--- a/gdb/testsuite/gdb.base/foll-exec.exp
+++ b/gdb/testsuite/gdb.base/foll-exec.exp
@@ -13,6 +13,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

+# This is a test of gdb's ability to follow a process through a
+# Unix exec() system call.
+
if { [is_remote target] || ![isnative] } then {
continue
}
@@ -44,44 +47,14 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $com
return -1
}

-proc zap_session {} {
- global gdb_prompt
- global binfile
-
- send_gdb "kill\n"
- gdb_expect {
- -re ".*Kill the program being debugged.*y or n. $" {
- gdb_test_no_output "y" ""
- send_gdb "file $binfile\n"
- gdb_expect {
- -re ".*Load new symbol table from.*y or n. $" {
- send_gdb "y\n"
- gdb_expect {
- -re "Reading symbols from.*$gdb_prompt $" {}
- timeout { fail "loading symbols (timeout)"; return }
- }
- }
- -re ".*gdb_prompt $" {}
- timeout { fail "loading symbols (timeout)"; return }
- }
- }
- -re ".*$gdb_prompt $" {}
- timeout { fail "killing inferior (timeout)" ; return }
- }
-}
-
proc do_exec_tests {} {
+ global binfile srcfile srcfile2 testfile testfile2
global gdb_prompt
- global binfile
- global srcfile
- global srcfile2
- global testfile
- global testfile2

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile}"
+ fail "Couldn't run ${testfile}"
return
}

@@ -103,12 +76,12 @@ proc do_exec_tests {} {
return
}

- zap_session
+ clean_restart $binfile

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile}"
+ fail "Couldn't run ${testfile}"
return
}

@@ -192,12 +165,12 @@ proc do_exec_tests {} {

# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- zap_session
+ clean_restart $binfile

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile} (2nd try)"
+ fail "Couldn't run ${testfile} (2nd try)"
return
}

@@ -265,12 +238,12 @@ proc do_exec_tests {} {

# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- zap_session
+ clean_restart $binfile

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile} (3rd try)"
+ fail "Couldn't run ${testfile} (3rd try)"
return
}

@@ -326,12 +299,12 @@ proc do_exec_tests {} {

# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- zap_session
+ clean_restart $binfile

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile} (4th try)"
+ fail "Couldn't run ${testfile} (4th try)"
return
}

@@ -381,12 +354,12 @@ proc do_exec_tests {} {

# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- zap_session
+ clean_restart $binfile

# Start the program running, and stop at main.
#
if ![runto_main] then {
- perror "Couldn't run ${testfile} (5th try)"
+ fail "Couldn't run ${testfile} (5th try)"
return
}

@@ -406,14 +379,8 @@ proc do_exec_tests {} {
# Start with a fresh gdb

gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
+clean_restart $binfile

-# This is a test of gdb's ability to follow a process through a
-# Unix exec() system call.
-#
do_exec_tests

return 0
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index b94b7ea..78c5cc8 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -524,23 +524,18 @@ with_test_prefix "check vfork support" {
check_vfork_catchpoints
}

-# There is no support for exec events in the RSP yet.
-if { ![gdb_is_target_remote] } {
- # Follow parent and follow child vfork tests with a child that execs.
- with_test_prefix "exec" {
- # These are tests of gdb's ability to follow the parent of a Unix
- # vfork system call. The child will subsequently call a variant
- # of the Unix exec system call.
- do_vfork_and_follow_parent_tests
-
- # These are tests of gdb's ability to follow the child of a Unix
- # vfork system call. The child will subsequently call a variant
- # of a Unix exec system call.
- #
- do_vfork_and_follow_child_tests_exec
- }
-} else {
- unsupported "vfork with exec: exec events not supported for remote"
+# Follow parent and follow child vfork tests with a child that execs.
+with_test_prefix "exec" {
+ # These are tests of gdb's ability to follow the parent of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of the Unix exec system call.
+ do_vfork_and_follow_parent_tests
+
+ # These are tests of gdb's ability to follow the child of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of a Unix exec system call.
+ #
+ do_vfork_and_follow_child_tests_exec
}

# Switch to test the case of the child exiting. We can't use
diff --git a/gdb/testsuite/gdb.base/pie-execl.exp b/gdb/testsuite/gdb.base/pie-execl.exp
index 182f96f..51edc82 100644
--- a/gdb/testsuite/gdb.base/pie-execl.exp
+++ b/gdb/testsuite/gdb.base/pie-execl.exp
@@ -16,6 +16,9 @@
# The problem was due to amd64_skip_prologue attempting to access inferior
# memory before the PIE (Position Independent Executable) gets relocated.

+global inferior_spawn_id
+global gdb_spawn_id
+
if ![istarget *-linux*] {
continue
}
@@ -67,6 +70,7 @@ gdb_test_multiple "p/x &pie_execl_marker" $test {
verbose -log "addr1 is $addr1"

set test "continue"
+set matches_found 0
gdb_test_multiple $test $test {
-re "Error in re-setting breakpoint" {
fail $test
@@ -74,8 +78,24 @@ gdb_test_multiple $test $test {
-re "Cannot access memory" {
fail $test
}
- -re "pie-execl: re-exec.*executing new program.*\r\nBreakpoint \[0-9\]+,\[^\r\n\]* pie_execl_marker .*\r\n$gdb_prompt $" {
- pass $test
+ -i "$inferior_spawn_id" -re "pie-execl: re-exec" {
+ # output from inferior
+ incr matches_found
+ if { $matches_found == 2 } {
+ pass $test
+ } else {
+ exp_continue
+ }
+ }
+ -i "$gdb_spawn_id"
+ -re "executing new program.*\r\nBreakpoint \[0-9\]+,\[^\r\n\]* pie_execl_marker .*\r\n$gdb_prompt $" {
+ # output from gdb
+ incr matches_found
+ if { $matches_found == 2 } {
+ pass $test
+ } else {
+ exp_continue
+ }
}
}

diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
index 69e5cc6..3e5c902 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-1.exp
@@ -28,11 +28,14 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}

-proc do_test { lock_sched } {
- with_test_prefix "lock-sched$lock_sched" {
+proc do_test { lock_sched nonstop } {
+ with_test_prefix "lock-sched$lock_sched,non-stop$nonstop" {
global executable

- clean_restart ${executable}
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop $nonstop\""
+ clean_restart ${executable}
+ }

if ![runto_main] {
return -1
@@ -48,11 +51,22 @@ proc do_test { lock_sched } {
gdb_test_no_output "set scheduler-locking on"
}

+ if { $nonstop == "on" } {
+ gdb_test "thread 2" "Switching.*"
+ }
+
gdb_test "continue" \
".*is executing new program.*Breakpoint 1, main.* at .*" \
"continue over exec"
}
}

-do_test 0
-do_test 1
+foreach nonstop {"on" "off"} {
+ foreach schedlock {"on" "off"} {
+ if {$schedlock == "on" && $nonstop == "on"} {
+ # Schedule locking has no effect in nonstop mode.
+ continue
+ }
+ do_test $schedlock $nonstop
+ }
+}
diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
index 9386153..5e25f22 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
@@ -29,11 +29,14 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}

-proc do_test { lock_sched } {
- with_test_prefix "lock-sched$lock_sched" {
+proc do_test { lock_sched nonstop } {
+ with_test_prefix "lock-sched$lock_sched,non-stop$nonstop" {
global executable

- clean_restart ${executable}
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop $nonstop\""
+ clean_restart ${executable}
+ }

if ![runto_main] {
return -1
@@ -42,6 +45,10 @@ proc do_test { lock_sched } {
gdb_breakpoint [gdb_get_line_number "break-here"]
gdb_continue_to_breakpoint "break-here" ".* break-here .*"

+ if { $nonstop == "on" } {
+ gdb_test "thread 2" "Switching.*"
+ }
+
gdb_test "info threads" \
"\r\n\[ \t\]*Id\[ \t\]+Target\[ \t\]+Id\[ \t\]+Frame\[ \t\]*\r\n\\* 2 *Thread \[^\r\n\]* at \[^\r\n\]*" \
"single thread left"
@@ -59,5 +66,12 @@ proc do_test { lock_sched } {
}
}

-do_test 0
-do_test 1
+foreach nonstop {"on" "off"} {
+ foreach schedlock {"on" "off"} {
+ if {$schedlock == "on" && $nonstop == "on"} {
+ # Schedule locking has no effect in nonstop mode.
+ continue
+ }
+ do_test $schedlock $nonstop
+ }
+}
diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-3.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-3.exp
index cc7da1a..8778471 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-3.exp
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-3.exp
@@ -31,18 +31,25 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}

-proc do_test { lock_sched } {
- with_test_prefix "lock-sched$lock_sched" {
+proc do_test { lock_sched nonstop } {
+ with_test_prefix "lock-sched$lock_sched,non-stop$nonstop" {
global executable

- clean_restart ${executable}
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop $nonstop\""
+ clean_restart ${executable}
+ }

if ![runto_main] {
return -1
}

gdb_breakpoint [gdb_get_line_number "break-here"]
- gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+ gdb_test_multiple "continue" "continue to breakpoint" {
+ -re ".*Breakpoint.*break-here.*" {
+ pass "continue to breakpoint"
+ }
+ }

# Also test with sched-lock to make sure we can follow the
# non-leader thread execing even though the main thread wasn't
@@ -51,11 +58,22 @@ proc do_test { lock_sched } {
gdb_test_no_output "set scheduler-locking on"
}

+ if { $nonstop == "on" } {
+ gdb_test "thread 2" "Switching.*"
+ }
+
gdb_test "continue" \
".*is executing new program.*Breakpoint 1, main.* at .*" \
"continue over exec"
}
}

-do_test 0
-do_test 1
+foreach nonstop {"on" "off"} {
+ foreach schedlock {"on" "off"} {
+ if {$schedlock == "on" && $nonstop == "on"} {
+ # Schedule locking has no effect in nonstop mode.
+ continue
+ }
+ do_test $schedlock $nonstop
+ }
+}
diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-4.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-4.exp
index a89b818..5723348 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-4.exp
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-4.exp
@@ -30,11 +30,14 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}

-proc do_test { lock_sched } {
- with_test_prefix "lock-sched$lock_sched" {
+proc do_test { lock_sched nonstop } {
+ with_test_prefix "lock-sched$lock_sched,non-stop$nonstop" {
global executable

- clean_restart ${executable}
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop $nonstop\""
+ clean_restart ${executable}
+ }

if ![runto_main] {
return -1
@@ -50,11 +53,22 @@ proc do_test { lock_sched } {
gdb_test_no_output "set scheduler-locking on"
}

+ if { $nonstop == "on" } {
+ gdb_test "thread 2" "Switching.*"
+ }
+
gdb_test "continue" \
".*is executing new program.*Breakpoint 1, main.* at .*" \
"continue over exec"
}
}

-do_test 0
-do_test 1
+foreach nonstop {"on" "off"} {
+ foreach schedlock {"on" "off"} {
+ if {$schedlock == "on" && $nonstop == "on"} {
+ # Schedule locking has no effect in nonstop mode.
+ continue
+ }
+ do_test $schedlock $nonstop
+ }
+}
--
1.8.1.1