From 8aeb23f3648c6ef10c5715e30f04563d1cc28709 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 17 Oct 2010 18:24:47 +0000 Subject: [PATCH] gdb/ * gdbthread.h (currently_stepping): New declaration. * infrun.c (currently_stepping): Remove the forward declaration. (currently_stepping): Make it global. * linux-nat.c (resume_callback) stopped && lp->status == 0>: New variables tp and step, initialized them. Pass STEP to to_resume. Print also possibly "PTRACE_SINGLESTEP" if STEP. Initialize LP->STEP. * remote.c (currently_stepping_callback): New. (remote_vcont_resume) : New variable tp. Call currently_stepping_callback and step such thread. gdb/testsuite/ * gdb.threads/sigstep-threads.exp: New file. * gdb.threads/sigstep-threads.c: New file. --- gdb/ChangeLog | 15 ++++ gdb/gdbthread.h | 2 + gdb/infrun.c | 4 +- gdb/linux-nat.c | 14 +++- gdb/remote.c | 14 ++++ gdb/testsuite/ChangeLog | 5 ++ gdb/testsuite/gdb.threads/sigstep-threads.c | 54 ++++++++++++++ gdb/testsuite/gdb.threads/sigstep-threads.exp | 74 +++++++++++++++++++ 8 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 gdb/testsuite/gdb.threads/sigstep-threads.c create mode 100644 gdb/testsuite/gdb.threads/sigstep-threads.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ba1268437c1..3cdd41c9151 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2010-10-17 Jan Kratochvil + Pedro Alves + + * gdbthread.h (currently_stepping): New declaration. + * infrun.c (currently_stepping): Remove the forward declaration. + (currently_stepping): Make it global. + * linux-nat.c (resume_callback) stopped && lp->status == 0>: New + variables tp and step, initialized them. Pass STEP to to_resume. + Print also possibly "PTRACE_SINGLESTEP" if STEP. Initialize LP->STEP. + * remote.c (currently_stepping_callback): New. + (remote_vcont_resume) + : + New variable tp. Call currently_stepping_callback and step such + thread. + 2010-10-17 Jan Kratochvil * infrun.c (follow_exec): Replace symbol_file_add_main by diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index cd24eaf2fb0..e89e88d346a 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -352,4 +352,6 @@ extern struct thread_info* inferior_thread (void); extern void update_thread_list (void); +extern int currently_stepping (struct thread_info *tp); + #endif /* GDBTHREAD_H */ diff --git a/gdb/infrun.c b/gdb/infrun.c index 240cd958fc4..edd4a40db64 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -74,8 +74,6 @@ static int follow_fork (void); static void set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c); -static int currently_stepping (struct thread_info *tp); - static int currently_stepping_or_nexting_callback (struct thread_info *tp, void *data); @@ -4851,7 +4849,7 @@ infrun: not switching back to stepped thread, it has vanished\n"); /* Is thread TP in the middle of single-stepping? */ -static int +int currently_stepping (struct thread_info *tp) { return ((tp->step_range_end && tp->step_resume_breakpoint == NULL) diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 0e18034994b..f8de481a694 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1820,20 +1820,26 @@ resume_callback (struct lwp_info *lp, void *data) } else if (lp->stopped && lp->status == 0) { + struct thread_info *tp = find_thread_ptid (lp->ptid); + /* lp->step may already contain a stale value. */ + int step = tp ? currently_stepping (tp) : 0; + if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "RC: PTRACE_CONT %s, 0, 0 (resuming sibling)\n", + "RC: %s %s, 0, 0 (resuming sibling)\n", + step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT", target_pid_to_str (lp->ptid)); linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)), - 0, TARGET_SIGNAL_0); + step, TARGET_SIGNAL_0); if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "RC: PTRACE_CONT %s, 0, 0 (resume sibling)\n", + "RC: %s %s, 0, 0 (resume sibling)\n", + step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT", target_pid_to_str (lp->ptid)); lp->stopped = 0; - lp->step = 0; + lp->step = step; memset (&lp->siginfo, 0, sizeof (lp->siginfo)); lp->stopped_by_watchpoint = 0; } diff --git a/gdb/remote.c b/gdb/remote.c index d6c20f343f2..13a96352c4b 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -4416,6 +4416,12 @@ append_resumption (char *p, char *endp, return p; } +static int +currently_stepping_callback (struct thread_info *tp, void *data) +{ + return currently_stepping (tp); +} + /* Resume the remote inferior by using a "vCont" packet. The thread to be resumed is PTID; STEP and SIGGNAL indicate whether the resumed thread should be single-stepped and/or signalled. If PTID @@ -4458,6 +4464,8 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) } else if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) { + struct thread_info *tp; + /* Resume all threads (of all processes, or of a single process), with preference for INFERIOR_PTID. This assumes inferior_ptid belongs to the set of all threads we are about @@ -4468,6 +4476,12 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) p = append_resumption (p, endp, inferior_ptid, step, siggnal); } + tp = iterate_over_threads (currently_stepping_callback, NULL); + if (tp && !ptid_equal (tp->ptid, inferior_ptid)) + { + p = append_resumption (p, endp, tp->ptid, 1, TARGET_SIGNAL_0); + } + /* And continue others without a signal. */ p = append_resumption (p, endp, ptid, /*step=*/ 0, TARGET_SIGNAL_0); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 65a71a9cd0c..d48b6d08d7c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-10-17 Jan Kratochvil + + * gdb.threads/sigstep-threads.exp: New file. + * gdb.threads/sigstep-threads.c: New file. + 2010-10-17 Jan Kratochvil * gdb.base/pie-execl.exp: New file. diff --git a/gdb/testsuite/gdb.threads/sigstep-threads.c b/gdb/testsuite/gdb.threads/sigstep-threads.c new file mode 100644 index 00000000000..7e04c32934f --- /dev/null +++ b/gdb/testsuite/gdb.threads/sigstep-threads.c @@ -0,0 +1,54 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 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 + +#include +#include +#define tgkill(tgid, tid, sig) syscall (__NR_tgkill, (tgid), (tid), (sig)) +#define gettid() syscall (__NR_gettid) + +static volatile int var; + +static void +handler (int signo) /* step-0 */ +{ /* step-0 */ + var++; /* step-1 */ + tgkill (getpid (), gettid (), SIGUSR1); /* step-2 */ +} + +static void * +start (void *arg) +{ + signal (SIGUSR1, handler); + tgkill (getpid (), gettid (), SIGUSR1); + assert (0); + + return NULL; +} + +int +main (void) +{ + pthread_t thread; + + pthread_create (&thread, NULL, start, NULL); + start (NULL); /* main-start */ + return 0; +} diff --git a/gdb/testsuite/gdb.threads/sigstep-threads.exp b/gdb/testsuite/gdb.threads/sigstep-threads.exp new file mode 100644 index 00000000000..511070649a8 --- /dev/null +++ b/gdb/testsuite/gdb.threads/sigstep-threads.exp @@ -0,0 +1,74 @@ +# Copyright 2010 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 . + +set testfile sigstep-threads +set srcfile ${testfile}.c +set executable ${testfile} +set binfile ${objdir}/${subdir}/${executable} + +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested ${testfile}.exp + return -1 +} + +clean_restart $executable + +if ![runto_main] { + return -1; +} + +# `noprint' would not test the full logic of GDB. +gdb_test "handle SIGUSR1 nostop print pass" "\r\nSIGUSR1\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\].*" + +gdb_test_no_output "set scheduler-locking off" + +gdb_breakpoint [gdb_get_line_number "step-1"] +gdb_test_no_output {set $step1=$bpnum} +gdb_continue_to_breakpoint "step-1" ".* step-1 .*" +gdb_test_no_output {disable $step1} + +# 1 as we are now stopped at the `step-1' label. +set step_at 1 +for {set i 0} {$i < 100} {incr i} { + set test "step $i" + # Presume this step failed - as in the case of a timeout. + set failed 1 + gdb_test_multiple "step" $test { + -re "\r\nProgram received signal SIGUSR1, User defined signal 1.\r\n" { + exp_continue -continue_timer + } + -re "step-(\[012\]).*\r\n$gdb_prompt $" { + set now $expect_out(1,string) + if {$step_at == 2 && $now == 1} { + set failed 0 + } elseif {$step_at == 1 && $now == 2} { + set failed 0 + # Continue over the re-signalling back to the handle entry. + gdb_test_no_output {enable $step1} "" + gdb_test "continue" " step-1 .*" "" + set now 1 + gdb_test_no_output {disable $step1} "" + } else { + fail $test + } + set step_at $now + } + } + if $failed { + return + } +} +# We can never reliably say the racy problematic case has been tested. +pass "step" -- 2.30.2