]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-stale-frame_info.patch
- typo
[packages/gdb.git] / gdb-stale-frame_info.patch
1 http://sourceware.org/ml/gdb-patches/2012-04/msg00058.html
2 Subject: [downstream patch FYI] workaround stale frame_info * (PR 13866)
3
4 Hi,
5
6 I did not look at which commit caused this regression but apparently it was
7 introduced at least with multi-inferiors.
8
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
14         gdb.multi/base.exp
15 so I had to put there that sorting magic.
16
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.
21
22 No regressions on {x86_64,x86_64-m32,i686}-fedora17-linux-gnu.
23
24
25 Thanks,
26 Jan
27
28
29 gdb/
30 2012-04-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
31
32         Workaround PR backtrace/13866.
33         * progspace.c (switch_to_program_space_and_thread): Try not to call
34         switch_to_thread.
35
36 --- a/gdb/progspace.c
37 +++ b/gdb/progspace.c
38 @@ -481,17 +481,28 @@ save_current_space_and_thread (void)
39  void
40  switch_to_program_space_and_thread (struct program_space *pspace)
41  {
42 -  struct inferior *inf;
43 +  struct inferior *inf = current_inferior ();
44  
45 -  inf = find_inferior_for_program_space (pspace);
46 +  if (inf->pspace != pspace)
47 +    inf = find_inferior_for_program_space (pspace);
48    if (inf != NULL)
49      {
50 -      struct thread_info *tp;
51 +      struct thread_info *tp, *current_tp = NULL;
52 +
53 +      if (ptid_get_pid (inferior_ptid) == inf->pid)
54 +       current_tp = find_thread_ptid (inferior_ptid);
55  
56        tp = any_live_thread_of_process (inf->pid);
57        if (tp != NULL)
58         {
59 -         switch_to_thread (tp->ptid);
60 +         /* Prefer primarily thread not THREAD_EXITED and secondarily thread
61 +            not EXECUTING.  */
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);
67 +
68           /* Switching thread switches pspace implicitly.  We're
69              done.  */
70           return;
71
72
73 Reproducer with:
74 ./gdb -nx ~/t/thread -ex 'b 24' -ex r -ex 'until 25'
75 Breakpoint 1, main () at /home/jkratoch/t/thread.c:24
76 24        v++;
77 Segmentation fault (core dumped)
78
79 #include <pthread.h>
80 #include <assert.h>
81 #include <unistd.h>
82
83 static int v;
84
85 static void *start (void *arg)
86 {
87   v++;
88   v++;
89   v++;
90   v++;
91   sleep (100);
92   return arg;
93 }
94
95 int main (void)
96 {
97   pthread_t thread1;
98   int i;
99
100   i = pthread_create (&thread1, NULL, start, NULL);
101   assert (i == 0);
102   v++;
103   v++;
104   v++;
105   v++;
106   i = pthread_join (thread1, NULL);
107   assert (i == 0);
108
109   return 0;
110 }
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 ();
115 ###  }
116 ###  
117 ### +typedef struct obstack obstack_s;
118 ### +DEF_VEC_O (obstack_s);
119 ### +static VEC (obstack_s) *frame_poison_vec;
120 ### +
121 ### +void frame_garbage_collection (void);
122 ### +void
123 ### +frame_garbage_collection (void)
124 ### +{
125 ### +  struct obstack *obstack_p;
126 ### +  int ix;
127 ### +
128 ### +  for (ix = 0; VEC_iterate (obstack_s, frame_poison_vec, ix, obstack_p); ix++)
129 ### +    obstack_free (obstack_p, 0);
130 ### +
131 ### +  VEC_free (obstack_s, frame_poison_vec);
132 ### +  frame_poison_vec = NULL;
133 ### +}
134 ### +
135 ###  /* Flush the entire frame cache.  */
136 ###  
137 ###  void
138 ###  reinit_frame_cache (void)
139 ###  {
140 ### -  struct frame_info *fi;
141 ### +  struct frame_info *fi, *fi_prev;
142 ###  
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);
147 ###      }
148 ###  
149 ### +  for (fi = current_frame; fi != NULL; fi = fi_prev)
150 ### +    {
151 ### +      fi_prev = fi->prev;
152 ### +      memset (fi, 0, sizeof (*fi));
153 ### +    }
154 ### +  VEC_safe_push (obstack_s, frame_poison_vec, &frame_cache_obstack);
155 ### +
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);
159 ###  
160 ###    if (current_frame != NULL)
161 ### --- a/gdb/top.c
162 ### +++ b/gdb/top.c
163 ### @@ -359,6 +359,11 @@ prepare_execute_command (void)
164 ###    if (non_stop)
165 ###      target_dcache_invalidate ();
166 ###  
167 ### +  {
168 ### +    extern void frame_garbage_collection (void);
169 ### +    frame_garbage_collection ();
170 ### +  }
171 ### +
172 ###    return cleanup;
173 ###  }
174 ###  
This page took 0.041997 seconds and 3 git commands to generate.