1 http://sourceware.org/ml/gdb-patches/2012-04/msg00058.html
2 Subject: [downstream patch FYI] workaround stale frame_info * (PR 13866)
6 I did not look at which commit caused this regression but apparently it was
7 introduced at least with multi-inferiors.
9 I understand this fix is not right fix of the crash; but in most GDB cases one
10 does not use multi-inferior so why to regress single-inferior by it.
11 Some more simple solutions still fix the single-inferior mode but they
12 regressed the multi-inferior mode
13 gdb.threads/no-unwaited-for-left.exp
15 so I had to put there that sorting magic.
17 With proper C++ sanity check of stale live frame_info references the testcase
18 would be simple without the "frame_garbage_collection" reproducer below.
19 It is also reproducible just with valgrind but regularly running the whole
20 testsuite under valgrind I did not find feasible.
22 No regressions on {x86_64,x86_64-m32,i686}-fedora17-linux-gnu.
30 2012-04-04 Jan Kratochvil <jan.kratochvil@redhat.com>
32 Workaround PR backtrace/13866.
33 * progspace.c (switch_to_program_space_and_thread): Try not to call
38 @@ -481,17 +481,28 @@ save_current_space_and_thread (void)
40 switch_to_program_space_and_thread (struct program_space *pspace)
42 - struct inferior *inf;
43 + struct inferior *inf = current_inferior ();
45 - inf = find_inferior_for_program_space (pspace);
46 + if (inf->pspace != pspace)
47 + inf = find_inferior_for_program_space (pspace);
50 - struct thread_info *tp;
51 + struct thread_info *tp, *current_tp = NULL;
53 + if (ptid_get_pid (inferior_ptid) == inf->pid)
54 + current_tp = find_thread_ptid (inferior_ptid);
56 tp = any_live_thread_of_process (inf->pid);
59 - switch_to_thread (tp->ptid);
60 + /* Prefer primarily thread not THREAD_EXITED and secondarily thread
62 + if (current_tp == NULL
63 + || (tp->state != THREAD_EXITED
64 + && current_tp->state == THREAD_EXITED)
65 + || (!tp->executing && current_tp->executing))
66 + switch_to_thread (tp->ptid);
68 /* Switching thread switches pspace implicitly. We're
74 ./gdb -nx ~/t/thread -ex 'b 24' -ex r -ex 'until 25'
75 Breakpoint 1, main () at /home/jkratoch/t/thread.c:24
77 Segmentation fault (core dumped)
85 static void *start (void *arg)
100 i = pthread_create (&thread1, NULL, start, NULL);
106 i = pthread_join (thread1, NULL);
111 ### --- a/gdb/frame.c
112 ### +++ b/gdb/frame.c
113 ### @@ -1522,12 +1522,30 @@ frame_observer_target_changed (struct target_ops *target)
114 ### reinit_frame_cache ();
117 ### +typedef struct obstack obstack_s;
118 ### +DEF_VEC_O (obstack_s);
119 ### +static VEC (obstack_s) *frame_poison_vec;
121 ### +void frame_garbage_collection (void);
123 ### +frame_garbage_collection (void)
125 ### + struct obstack *obstack_p;
128 ### + for (ix = 0; VEC_iterate (obstack_s, frame_poison_vec, ix, obstack_p); ix++)
129 ### + obstack_free (obstack_p, 0);
131 ### + VEC_free (obstack_s, frame_poison_vec);
132 ### + frame_poison_vec = NULL;
135 ### /* Flush the entire frame cache. */
138 ### reinit_frame_cache (void)
140 ### - struct frame_info *fi;
141 ### + struct frame_info *fi, *fi_prev;
143 ### /* Tear down all frame caches. */
144 ### for (fi = current_frame; fi != NULL; fi = fi->prev)
145 ### @@ -1538,8 +1556,14 @@ reinit_frame_cache (void)
146 ### fi->base->unwind->dealloc_cache (fi, fi->base_cache);
149 ### + for (fi = current_frame; fi != NULL; fi = fi_prev)
151 ### + fi_prev = fi->prev;
152 ### + memset (fi, 0, sizeof (*fi));
154 ### + VEC_safe_push (obstack_s, frame_poison_vec, &frame_cache_obstack);
156 ### /* Since we can't really be sure what the first object allocated was. */
157 ### - obstack_free (&frame_cache_obstack, 0);
158 ### obstack_init (&frame_cache_obstack);
160 ### if (current_frame != NULL)
163 ### @@ -359,6 +359,11 @@ prepare_execute_command (void)
165 ### target_dcache_invalidate ();
168 ### + extern void frame_garbage_collection (void);
169 ### + frame_garbage_collection ();