Blob Blame History Raw
http://sourceware.org/ml/gdb-patches/2012-04/msg00058.html
Subject: [downstream patch FYI] workaround stale frame_info * (PR 13866)

Hi,

I did not look at which commit caused this regression but apparently it was
introduced at least with multi-inferiors.

I understand this fix is not right fix of the crash; but in most GDB cases one
does not use multi-inferior so why to regress single-inferior by it.
Some more simple solutions still fix the single-inferior mode but they
regressed the multi-inferior mode
	gdb.threads/no-unwaited-for-left.exp
	gdb.multi/base.exp
so I had to put there that sorting magic.

With proper C++ sanity check of stale live frame_info references the testcase
would be simple without the "frame_garbage_collection" reproducer below.
It is also reproducible just with valgrind but regularly running the whole
testsuite under valgrind I did not find feasible.

No regressions on {x86_64,x86_64-m32,i686}-fedora17-linux-gnu.


Thanks,
Jan


gdb/
2012-04-04  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Workaround PR backtrace/13866.
	* progspace.c (switch_to_program_space_and_thread): Try not to call
	switch_to_thread.

Index: gdb-7.3.50.20110722/gdb/progspace.c
===================================================================
--- gdb-7.3.50.20110722.orig/gdb/progspace.c	2011-01-05 23:22:50.000000000 +0100
+++ gdb-7.3.50.20110722/gdb/progspace.c	2012-04-04 23:07:16.329038403 +0200
@@ -480,17 +480,36 @@ save_current_space_and_thread (void)
 void
 switch_to_program_space_and_thread (struct program_space *pspace)
 {
-  struct inferior *inf;
+  struct inferior *inf = current_inferior ();
 
-  inf = find_inferior_for_program_space (pspace);
+  if (inf->pspace != pspace)
+    inf = find_inferior_for_program_space (pspace);
   if (inf != NULL)
     {
-      struct thread_info *tp;
+      struct thread_info *tp, *current_tp = NULL;
+
+      if (ptid_get_pid (inferior_ptid) == inf->pid)
+	current_tp = find_thread_ptid (inferior_ptid);
 
       tp = any_live_thread_of_process (inf->pid);
       if (tp != NULL)
 	{
-	  switch_to_thread (tp->ptid);
+	  /* thread.c */
+	  enum thread_state
+	  {
+	    THREAD_STOPPED,
+	    THREAD_RUNNING,
+	    THREAD_EXITED,
+	  };
+
+	  /* Prefer primarily thread not THREAD_EXITED and secondarily thread
+	     not EXECUTING.  */
+	  if (current_tp == NULL
+	      || (tp->state_ != THREAD_EXITED
+		  && current_tp->state_ == THREAD_EXITED)
+	      || (!tp->executing_ && current_tp->executing_))
+	    switch_to_thread (tp->ptid);
+
 	  /* Switching thread switches pspace implicitly.  We're
 	     done.  */
 	  return;