From a75724bceb9e90bfb5ee80916cfcd8f2b87041f4 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 27 May 2009 19:44:53 +0000 Subject: [PATCH] gdb/ * infrun.c (follow_exec): Clear the stop_requested flag. * linux-nat.c (linux_handle_extended_wait) : Add debug output. gdb/testsuite/ * gdb.mi/nsthrexec.c, gdb.mi/mi-nsthrexec.exp: New. --- gdb/ChangeLog | 6 ++ gdb/infrun.c | 8 +++ gdb/linux-nat.c | 5 ++ gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.mi/mi-nsthrexec.exp | 101 ++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.mi/nsthrexec.c | 48 ++++++++++++++++ 6 files changed, 172 insertions(+) create mode 100644 gdb/testsuite/gdb.mi/mi-nsthrexec.exp create mode 100644 gdb/testsuite/gdb.mi/nsthrexec.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 07f3e0f..3cf2a01 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2009-05-27 Pedro Alves + + * infrun.c (follow_exec): Clear the stop_requested flag. + * linux-nat.c (linux_handle_extended_wait) : + Add debug output. + 2009-05-27 Aleksandar Ristovski * nto-procfs.c (get_regset): Pass correct pointer. diff --git a/gdb/infrun.c b/gdb/infrun.c index 7d870eb..381d208 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -494,6 +494,14 @@ follow_exec (ptid_t pid, char *execd_pathname) th->step_range_start = 0; th->step_range_end = 0; + /* The target reports the exec event to the main thread, even if + some other thread does the exec, and even if the main thread was + already stopped --- if debugging in non-stop mode, it's possible + the user had the main thread held stopped in the previous image + --- release it now. This is the same behavior as step-over-exec + with scheduler-locking on in all-stop mode. */ + th->stop_requested = 0; + /* What is this a.out's name? */ printf_unfiltered (_("Executing new program: %s\n"), execd_pathname); diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index c3cce49..edb4019 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1892,6 +1892,11 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, if (event == PTRACE_EVENT_EXEC) { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LHEW: Got exec event from LWP %ld\n", + GET_LWP (lp->ptid)); + ourstatus->kind = TARGET_WAITKIND_EXECD; ourstatus->value.execd_pathname = xstrdup (linux_child_pid_to_exec_file (pid)); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 5fabccc..dc55999 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-05-27 Pedro Alves + + * gdb.mi/nsthrexec.c, gdb.mi/mi-nsthrexec.exp: New. + 2009-05-24 Pedro Alves * gdb.threads/fork-thread-pending.c: New. diff --git a/gdb/testsuite/gdb.mi/mi-nsthrexec.exp b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp new file mode 100644 index 0000000..9d48376 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp @@ -0,0 +1,101 @@ +# Copyright 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 . + +# Test that when a thread other than the main thread execs, and the +# main thread was stopped due to user request, the new incarnation of +# the main thread doesn't just silently stop at the first internal +# breakpoint (usually the _dl_debug_state breakpoint). + +# No exec event support in the remote protocol. +if { [is_remote target] } then { + continue +} + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if {[mi_gdb_start]} { + continue +} + +# +# Start here +# +set testfile "nsthrexec" +set srcfile "$testfile.c" +set binfile "$objdir/$subdir/mi-$testfile" + +set options [list debug incdir=$objdir] +if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } { + return -1 +} + +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load $binfile + +set supported 0 +send_gdb "-gdb-show non-stop\n" +gdb_expect { + -re ".*\\^done,value=\"off\",supported=\"(\[^\"\]+)\"\r\n$mi_gdb_prompt$" { + if { $expect_out(1,string) == "1" } { + set supported 1 + } + } + -re ".$mi_gdb_prompt$" { + } +} + +mi_gdb_test "-gdb-set non-stop 1" ".*" +mi_gdb_test "-gdb-set target-async 1" ".*" +detect_async + +if { [mi_run_to_main] < 0 } { + perror "mi-nsthrexec.exp tests suppressed" + continue +} + +mi_create_breakpoint thread_execler 2 keep thread_execler .* .* .* \ + "breakpoint at thread_execler" + +# All threads should stop, except the main thread. +mi_send_resuming_command "exec-continue --all" "resume all" +mi_expect_stop "breakpoint-hit" "thread_execler" "\[^\n\]*" "$srcfile" \ + "\[0-9\]*" {"" "disp=\"keep\""} "stop at thread_execler" + +mi_check_thread_states \ + {"running" "stopped"} \ + "thread state, execler stopped, main running" + +mi_gdb_test "200-exec-interrupt --thread 1" "200\\^done" "interrupt main thread" +mi_expect_interrupt "main thread interrupted" + +mi_check_thread_states {"stopped" "stopped"} "thread state, all stopped" + +# now that we know about all the threads, we can get rid of the breakpoints +mi_delete_breakpoints + +mi_create_breakpoint main 3 keep main .* .* .* \ + "breakpoint at main" + +# Now resume the execler thread. Eventually, it execs. +mi_send_resuming_command "exec-continue --thread 2" "resume execler thread" + +# Check that the main thread passes by the _dl_debug_state internal +# breakpoint without silently stopping. +mi_expect_stop "breakpoint-hit" "main" "\[^\n\]*" "$srcfile" \ + "\[0-9\]*" {"" "disp=\"keep\""} "stop at main after exec" + +mi_gdb_exit diff --git a/gdb/testsuite/gdb.mi/nsthrexec.c b/gdb/testsuite/gdb.mi/nsthrexec.c new file mode 100644 index 0000000..ec23535 --- /dev/null +++ b/gdb/testsuite/gdb.mi/nsthrexec.c @@ -0,0 +1,48 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 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 . */ + +#include +#include +#include + +static const char *image; + +void * +thread_execler (void *arg) +{ + /* Exec ourselves again. */ + if (execl (image, image, NULL) == -1) + { + perror ("execl"); + abort (); + } + + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_t thread; + + image = argv[0]; + + pthread_create (&thread, NULL, thread_execler, NULL); + pthread_join (thread, NULL); + + return 0; +} -- 2.7.4