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]

Fix a multiprocess crash.


With the previous patch about the thread selection in
multi process installed, one also needs this patch.  I checked it
in.

The problem I had found was:

 After detaching from a process that was stopped at a breakpoint, while
others were still around to debug, when I switched to another thread
and resumed, I found the GDB was asking the remote stub about
registers of a thread that belonged to the process we had already
detached from.  This was resulting in confusing remote protocol errors
and/or GDB crashes.  What was happening was that prepare_to_proceed
thought we were still stopped at a breakpoint of the previous stop,
and was trying to tell the thread that is gone already to get over
that breakpoint.  This was now happening since
nullify_last_target_wait_ptid is no longer called from
remote.c:remote_mourn_inferior_1 (good), but, we still need to do
something to prevent this from happening.  This patch fixes it by
adding a new infrun observer for thread exits, that clears the last
target event if the corresponding thread is deleted.  The only issue
is that the observer is sometimes suppressed for MI's benefit.  So,
I've added a new parameter to the observer, and made MI itself decide
to ignore the event or not.  The MI change should be fairly obvious.
We may want to add more granularity in the future, but this is enough
for all current uses.  And yes, we do need to do something about
these inferior control globals at some point.

Tested on x86_64-linux.

-- 
Pedro Alves

gdb/
2000-03-25  Pedro Alves  <pedro@codesourcery.com>

	* infrun.c (infrun_thread_thread_exit): New.
	(_initialize_infrun): Attach it to the thread_exit observer.
	* thread.c (delete_thread_1): Always call the observer, passing it
	the silent flag.
	* mi/mi-interp.c (mi_thread_exit): Add "silent" parameter.  If
	SILENT, return immediately.

gdb/doc/
2000-03-25  Pedro Alves  <pedro@codesourcery.com>

	* observer.texi (thread_exit): Add "silent" parameter.

---
 gdb/doc/observer.texi |    6 ++++--
 gdb/infrun.c          |   10 ++++++++++
 gdb/mi/mi-interp.c    |   11 ++++++++---
 gdb/thread.c          |    7 +++----
 4 files changed, 25 insertions(+), 9 deletions(-)

Index: src/gdb/doc/observer.texi
===================================================================
--- src.orig/gdb/doc/observer.texi	2009-03-25 04:23:11.000000000 +0000
+++ src/gdb/doc/observer.texi	2009-03-25 16:14:10.000000000 +0000
@@ -134,8 +134,10 @@ previously loaded symbol table data has 
 The thread specified by @var{t} has been created.
 @end deftypefun
 
-@deftypefun void thread_exit (struct thread_info *@var{t})
-The thread specified by @var{t} has exited.
+@deftypefun void thread_exit (struct thread_info *@var{t}, int @var{silent})
+The thread specified by @var{t} has exited.  The @var{silent} argument
+indicates that @value{GDBN} is removing the thread from its tables
+without wanting to notify the user about it.
 @end deftypefun
 
 @deftypefun void thread_stop_requested (ptid_t @var{ptid})
Index: src/gdb/mi/mi-interp.c
===================================================================
--- src.orig/gdb/mi/mi-interp.c	2009-03-25 04:23:11.000000000 +0000
+++ src/gdb/mi/mi-interp.c	2009-03-25 04:24:39.000000000 +0000
@@ -55,7 +55,7 @@ static void mi_remove_notify_hooks (void
 static void mi_on_normal_stop (struct bpstats *bs, int print_frame);
 
 static void mi_new_thread (struct thread_info *t);
-static void mi_thread_exit (struct thread_info *t);
+static void mi_thread_exit (struct thread_info *t, int silent);
 static void mi_new_inferior (int pid);
 static void mi_inferior_exit (int pid);
 static void mi_on_resume (ptid_t ptid);
@@ -293,9 +293,14 @@ mi_new_thread (struct thread_info *t)
 }
 
 static void
-mi_thread_exit (struct thread_info *t)
+mi_thread_exit (struct thread_info *t, int silent)
 {
-  struct mi_interp *mi = top_level_interpreter_data ();
+  struct mi_interp *mi;
+
+  if (silent)
+    return;
+
+  mi = top_level_interpreter_data ();
   target_terminal_ours ();
   fprintf_unfiltered (mi->event_channel, 
 		      "thread-exited,id=\"%d\",group-id=\"%d\"", 
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2009-03-25 04:24:38.000000000 +0000
+++ src/gdb/infrun.c	2009-03-25 04:24:39.000000000 +0000
@@ -1691,6 +1691,15 @@ infrun_thread_stop_requested (ptid_t pti
   iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
 }
 
+void nullify_last_target_wait_ptid (void);
+
+static void
+infrun_thread_thread_exit (struct thread_info *tp, int silent)
+{
+  if (ptid_equal (target_last_wait_ptid, tp->ptid))
+    nullify_last_target_wait_ptid ();
+}
+
 /* Callback for iterate_over_threads.  */
 
 static int
@@ -5575,6 +5584,7 @@ Options are 'forward' or 'reverse'."),
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
   observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+  observer_attach_thread_exit (infrun_thread_thread_exit);
 
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
Index: src/gdb/thread.c
===================================================================
--- src.orig/gdb/thread.c	2009-03-25 04:24:38.000000000 +0000
+++ src/gdb/thread.c	2009-03-25 04:24:39.000000000 +0000
@@ -247,8 +247,7 @@ delete_thread_1 (ptid_t ptid, int silent
     {
       if (tp->state_ != THREAD_EXITED)
 	{
-	  if (!silent)
-	    observer_notify_thread_exit (tp);
+	  observer_notify_thread_exit (tp, silent);
 
 	  /* Tag it as exited.  */
 	  tp->state_ = THREAD_EXITED;
@@ -267,8 +266,8 @@ delete_thread_1 (ptid_t ptid, int silent
     thread_list = tp->next;
 
   /* Notify thread exit, but only if we haven't already.  */
-  if (!silent && tp->state_ != THREAD_EXITED)
-    observer_notify_thread_exit (tp);
+  if (tp->state_ != THREAD_EXITED)
+    observer_notify_thread_exit (tp, silent);
 
   free_thread (tp);
 }


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