This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH with testcase] Bug 11568 - delete thread-specific breakpoint on the thread exit


On 08/02/2013 02:45 PM, Pedro Alves wrote:
On 08/01/2013 01:43 PM, Muhammad Waqas wrote:
+			    || !target_thread_alive (tp->ptid)))
+	if ( tp != NULL && (tp->state == THREAD_EXITED
+			    || !target_thread_alive (tp->ptid)))
Do we really need this target_thread_alive call?  It
means we have extra remote traffic whenever we have a thread
specific breakpoint in the list.  If the user (or GDB itself)
hasn't refreshed the thread list, is there any harm in delaying
deleting the breakpoint?

But, I think I agree with Yao in that this doesn't look like
the right way to do this.

In fact, breakpoint_auto_delete is only called when the
target reports some stop.  If you're trying to delete
stale thread specific breakpoints, then you'd want to
do that even if the target hasn't reported a stop, right?

Say, in non-stop mode, w/ the remote target, if you have two
threads, set a thread-specific break on thread 2, and while
all threads are running free in busy loops, not reporting
any event, keep doing "info threads", and "info break".  At some
point thread #2 exits.  You can see that from "info threads".
But "info break" will still show you the stale breakpoint...
If breakpoint will be deleted when thread list is updated through
user or GDB and also when info break command is executed
by user, Will it work? What will you say about this technique?

I wouldn't even consider special casing "info break".  Otherwise,
you end up considering whether to handle all sorts of breakpoint
manipulation commands, like "enable", "disable", etc., and what
to do if the thread is already gone.

Tie this to GDB's own lifetime of the inferior's threads.  If GDB
learns the thread is gone, remove the breakpoint.  Otherwise,
leave it there.  Whether to remove the breakpoint immediately,
or mark it as disp_del_at_next_stop (and hide it, say, set its
bp->num to 0) is another question.  You'll note that
clear_thread_inferior_resources does the latter.  (That's because
most of GDB's native targets can't touch memory of running processes.)


Thanks for review and helping me out.

Now I register a function for deletion of breakpoint with thread_exit if breakpoint
is on thread so breakpoint will be deleted when thread finished.

Changlog

2013-08-05  Muhammad Waqas  <mwaqas@codesourcery.com>

	PR gdb/11568
	* breakpoint.c (remove_threaded_breakpoints): New function.
	* breakpoint.c (install_breakpoint): If breakpoint is on specific
	thread remove_threaded_breakpoints will be registered with thread_exit.


Index: ./../../breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.773
diff -u -p -r1.773 breakpoint.c
--- ./../../breakpoint.c	24 Jul 2013 19:50:32 -0000	1.773
+++ ./../../breakpoint.c	5 Aug 2013 11:51:43 -0000
@@ -200,6 +200,8 @@ typedef enum
   }
 insertion_state_t;
+static void remove_threaded_breakpoints (struct thread_info *tp, int silent);
+
 static int remove_breakpoint (struct bp_location *, insertion_state_t);
 static int remove_breakpoint_1 (struct bp_location *, insertion_state_t);
@@ -2928,6 +2930,21 @@ remove_breakpoints (void)
   return val;
 }
+static void
+remove_threaded_breakpoints(struct thread_info *tp, int silent)
+{
+  struct breakpoint *b, *b_tmp;
+
+  ALL_BREAKPOINTS_SAFE (b, b_tmp)
+    {
+      if (b->thread == tp->num)
+	{
+	  b->disposition = disp_del_at_next_stop;
+	  b->number = 0;
+	}
+    }
+}
+
 /* Remove breakpoints of process PID.  */
int
@@ -8450,7 +8467,12 @@ install_breakpoint (int internal, struct
   if (!internal)
     mention (b);
   observer_notify_breakpoint_created (b);
-
+
+  if (b->thread > 0)
+    {
+      observer_attach_thread_exit (remove_threaded_breakpoints);
+    }
+
   if (update_gll)
     update_global_location_list (1);
 }

Changlog

2013-07-24  Muhammad Waqas  <mwaqas@codesourccery.com>
	    Jan Kratochvil  <jan.kartochvil@redhat.com>

	PR gdb/11568
	*gdb.thread/thread-specific-bp.c: Newfile.
	*gdb.thread/thread-specific-bp.exp: Newfile.


testcase now testing All stop and non stop mode explicitly

Index: thread-specific-bp.c
===================================================================
RCS file: thread-specific-bp.c
diff -N thread-specific-bp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ thread-specific-bp.c	5 Aug 2013 11:51:51 -0000
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 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 <pthread.h>
+
+static void *
+start (void *arg)
+{
+  return NULL;
+}
+
+int
+main (void)
+{
+  pthread_t thread;
+  pthread_create (&thread, NULL, start, NULL);
+  pthread_join (thread, NULL);
+  return 0; /*set break here*/
+}
Index: thread-specific-bp.exp
===================================================================
RCS file: thread-specific-bp.exp
diff -N thread-specific-bp.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ thread-specific-bp.exp	5 Aug 2013 11:52:03 -0000
@@ -0,0 +1,84 @@
+# Copyright (C) 2013 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/>.
+#
+# Verify that a thread-specific breakpoint is deleted when the
+# corresponding thread is gone.
+
+standard_testfile
+
+set mode "All stop"
+
+if {[gdb_compile_pthreads \
+	 "${srcdir}/${subdir}/${srcfile}" \
+	 "${binfile}" executable {debug} ] != "" } {
+    return -1
+}
+
+clean_restart ${binfile}
+
+proc check_threaded_breakpoint {} {
+    global gdb_prompt mode
+    gdb_breakpoint "start"
+    gdb_continue_to_breakpoint "start"
+    set thre 0
+    gdb_test_multiple "info threads" "get thread 1 id" {
+	-re "(\[0-9\]+)(\[^\n\r\]*Thread\[^\n\r\]*start.*)($gdb_prompt $)" {
+	    pass "$mode: thread created"
+	    # get the id of thread
+	    set thre $expect_out(1,string)
+	}
+    }
+    gdb_breakpoint [gdb_get_line_number "set break here"]
+
+    # Force GDB to update its knowledge on existing threads when this
+    # breakpoint is hit.  Otherwise, GDB doesn't realize thread $thre
+    # has exited and doesn't remove the thread specific breakpoint.
+    gdb_test "commands\ninfo threads\nend" "End with.*" "$mode: add breakpoint commands"
+    gdb_breakpoint "main thread $thre"
+    gdb_test "info break" ".*breakpoint.*thread $thre" "$mode: Breakpoint set"
+    gdb_test "thread $thre" "Switching to thread $thre.*" "$mode: Thread $thre selected"
+    gdb_continue_to_breakpoint "$mode: set break here"
+    set test "$mode: thread-specific breakpoint is deleted"
+    gdb_test_multiple "info breakpoint" $test {
+    	-re "thread $thre.*$gdb_prompt $" {
+	    fail $test
+    	}
+    	-re "$gdb_prompt $" {
+	    pass $test
+    	}
+    }
+}
+
+if ![runto_main] {
+    untested "could not run to main"
+    return -1
+}
+
+# Testing in all stop mode.
+check_threaded_breakpoint
+
+clean_restart ${binfile}
+
+gdb_test "set target-async on" ".*" "Set async mode"
+gdb_test "set non-stop on" ".*" "Set non stop mode"
+
+if ![runto_main] {
+    untested "could not run to main"
+    return -1
+}
+
+# Testing in non-stop+async mode.
+set mode "non-stop\\async"
+check_threaded_breakpoint


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]