From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 From: Fedora GDB patches Date: Fri, 27 Oct 2017 21:07:50 +0200 Subject: workaround stale frame_info * (PR 13866) FileName: gdb-stale-frame_info.patch ;; Workaround crashes from stale frame_info pointer (BZ 804256). ;;=push+jan http://sourceware.org/ml/gdb-patches/2012-04/msg00058.html 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 Workaround PR backtrace/13866. * progspace.c (switch_to_program_space_and_thread): Try not to call switch_to_thread. diff --git a/gdb/progspace-and-thread.c b/gdb/progspace-and-thread.c --- a/gdb/progspace-and-thread.c +++ b/gdb/progspace-and-thread.c @@ -23,15 +23,29 @@ void switch_to_program_space_and_thread (program_space *pspace) { - inferior *inf = find_inferior_for_program_space (pspace); + inferior *inf = current_inferior (); + + if (inf->pspace != pspace) + inf = find_inferior_for_program_space (pspace); if (inf != NULL && inf->pid != 0) { thread_info *tp = any_live_thread_of_process (inf->pid); + thread_info *current_tp = NULL; + + if (ptid_get_pid (inferior_ptid) == inf->pid) + current_tp = find_thread_ptid (inferior_ptid); if (tp != NULL) { - switch_to_thread (tp->ptid); + /* 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;