]>
Commit | Line | Data |
---|---|---|
f3c378e8 AG |
1 | To: vim-dev@vim.org |
2 | Subject: Patch 7.0.135 | |
3 | Fcc: outbox | |
4 | From: Bram Moolenaar <Bram@moolenaar.net> | |
5 | Mime-Version: 1.0 | |
6 | Content-Type: text/plain; charset=ISO-8859-1 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ------------ | |
9 | ||
10 | Patch 7.0.135 | |
11 | Problem: Crash when garbage collecting list or dict with loop. | |
12 | Solution: Don't use DEL_REFCOUNT but don't recurse into Lists and | |
13 | Dictionaries when freeing them in the garbage collector. | |
14 | Also add allocated Dictionaries to the list of Dictionaries to | |
15 | avoid leaking memory. | |
16 | Files: src/eval.c, src/proto/eval.pro, src/tag.c | |
17 | ||
18 | ||
19 | *** ../vim-7.0.134/src/eval.c Sun Oct 15 15:10:08 2006 | |
20 | --- src/eval.c Sun Oct 15 22:30:09 2006 | |
21 | *************** | |
22 | *** 191,198 **** | |
23 | #define FC_RANGE 2 /* function accepts range */ | |
24 | #define FC_DICT 4 /* Dict function, uses "self" */ | |
25 | ||
26 | - #define DEL_REFCOUNT 999999 /* list/dict is being deleted */ | |
27 | - | |
28 | /* | |
29 | * All user-defined functions are found in this hashtable. | |
30 | */ | |
31 | --- 191,196 ---- | |
32 | *************** | |
33 | *** 435,441 **** | |
34 | static void set_ref_in_list __ARGS((list_T *l, int copyID)); | |
35 | static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); | |
36 | static void dict_unref __ARGS((dict_T *d)); | |
37 | ! static void dict_free __ARGS((dict_T *d)); | |
38 | static dictitem_T *dictitem_alloc __ARGS((char_u *key)); | |
39 | static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); | |
40 | static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); | |
41 | --- 433,439 ---- | |
42 | static void set_ref_in_list __ARGS((list_T *l, int copyID)); | |
43 | static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); | |
44 | static void dict_unref __ARGS((dict_T *d)); | |
45 | ! static void dict_free __ARGS((dict_T *d, int recurse)); | |
46 | static dictitem_T *dictitem_alloc __ARGS((char_u *key)); | |
47 | static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); | |
48 | static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); | |
49 | *************** | |
50 | *** 4899,4905 **** | |
51 | { | |
52 | if (list_append_tv(l, &item->li_tv) == FAIL) | |
53 | { | |
54 | ! list_free(l); | |
55 | return FAIL; | |
56 | } | |
57 | item = item->li_next; | |
58 | --- 4897,4903 ---- | |
59 | { | |
60 | if (list_append_tv(l, &item->li_tv) == FAIL) | |
61 | { | |
62 | ! list_free(l, TRUE); | |
63 | return FAIL; | |
64 | } | |
65 | item = item->li_next; | |
66 | *************** | |
67 | *** 5299,5305 **** | |
68 | EMSG2(_("E697: Missing end of List ']': %s"), *arg); | |
69 | failret: | |
70 | if (evaluate) | |
71 | ! list_free(l); | |
72 | return FAIL; | |
73 | } | |
74 | ||
75 | --- 5297,5303 ---- | |
76 | EMSG2(_("E697: Missing end of List ']': %s"), *arg); | |
77 | failret: | |
78 | if (evaluate) | |
79 | ! list_free(l, TRUE); | |
80 | return FAIL; | |
81 | } | |
82 | ||
83 | *************** | |
84 | *** 5363,5370 **** | |
85 | list_unref(l) | |
86 | list_T *l; | |
87 | { | |
88 | ! if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0) | |
89 | ! list_free(l); | |
90 | } | |
91 | ||
92 | /* | |
93 | --- 5361,5368 ---- | |
94 | list_unref(l) | |
95 | list_T *l; | |
96 | { | |
97 | ! if (l != NULL && --l->lv_refcount <= 0) | |
98 | ! list_free(l, TRUE); | |
99 | } | |
100 | ||
101 | /* | |
102 | *************** | |
103 | *** 5372,5385 **** | |
104 | * Ignores the reference count. | |
105 | */ | |
106 | void | |
107 | ! list_free(l) | |
108 | ! list_T *l; | |
109 | { | |
110 | listitem_T *item; | |
111 | ||
112 | - /* Avoid that recursive reference to the list frees us again. */ | |
113 | - l->lv_refcount = DEL_REFCOUNT; | |
114 | - | |
115 | /* Remove the list from the list of lists for garbage collection. */ | |
116 | if (l->lv_used_prev == NULL) | |
117 | first_list = l->lv_used_next; | |
118 | --- 5370,5381 ---- | |
119 | * Ignores the reference count. | |
120 | */ | |
121 | void | |
122 | ! list_free(l, recurse) | |
123 | ! list_T *l; | |
124 | ! int recurse; /* Free Lists and Dictionaries recursively. */ | |
125 | { | |
126 | listitem_T *item; | |
127 | ||
128 | /* Remove the list from the list of lists for garbage collection. */ | |
129 | if (l->lv_used_prev == NULL) | |
130 | first_list = l->lv_used_next; | |
131 | *************** | |
132 | *** 5392,5398 **** | |
133 | { | |
134 | /* Remove the item before deleting it. */ | |
135 | l->lv_first = item->li_next; | |
136 | ! listitem_free(item); | |
137 | } | |
138 | vim_free(l); | |
139 | } | |
140 | --- 5388,5397 ---- | |
141 | { | |
142 | /* Remove the item before deleting it. */ | |
143 | l->lv_first = item->li_next; | |
144 | ! if (recurse || (item->li_tv.v_type != VAR_LIST | |
145 | ! && item->li_tv.v_type != VAR_DICT)) | |
146 | ! clear_tv(&item->li_tv); | |
147 | ! vim_free(item); | |
148 | } | |
149 | vim_free(l); | |
150 | } | |
151 | *************** | |
152 | *** 6113,6119 **** | |
153 | for (dd = first_dict; dd != NULL; ) | |
154 | if (dd->dv_copyID != copyID) | |
155 | { | |
156 | ! dict_free(dd); | |
157 | did_free = TRUE; | |
158 | ||
159 | /* restart, next dict may also have been freed */ | |
160 | --- 6118,6127 ---- | |
161 | for (dd = first_dict; dd != NULL; ) | |
162 | if (dd->dv_copyID != copyID) | |
163 | { | |
164 | ! /* Free the Dictionary and ordinary items it contains, but don't | |
165 | ! * recurse into Lists and Dictionaries, they will be in the list | |
166 | ! * of dicts or list of lists. */ | |
167 | ! dict_free(dd, FALSE); | |
168 | did_free = TRUE; | |
169 | ||
170 | /* restart, next dict may also have been freed */ | |
171 | *************** | |
172 | *** 6130,6136 **** | |
173 | for (ll = first_list; ll != NULL; ) | |
174 | if (ll->lv_copyID != copyID && ll->lv_watch == NULL) | |
175 | { | |
176 | ! list_free(ll); | |
177 | did_free = TRUE; | |
178 | ||
179 | /* restart, next list may also have been freed */ | |
180 | --- 6138,6147 ---- | |
181 | for (ll = first_list; ll != NULL; ) | |
182 | if (ll->lv_copyID != copyID && ll->lv_watch == NULL) | |
183 | { | |
184 | ! /* Free the List and ordinary items it contains, but don't recurse | |
185 | ! * into Lists and Dictionaries, they will be in the list of dicts | |
186 | ! * or list of lists. */ | |
187 | ! list_free(ll, FALSE); | |
188 | did_free = TRUE; | |
189 | ||
190 | /* restart, next list may also have been freed */ | |
191 | *************** | |
192 | *** 6223,6233 **** | |
193 | d = (dict_T *)alloc(sizeof(dict_T)); | |
194 | if (d != NULL) | |
195 | { | |
196 | ! /* Add the list to the hashtable for garbage collection. */ | |
197 | if (first_dict != NULL) | |
198 | first_dict->dv_used_prev = d; | |
199 | d->dv_used_next = first_dict; | |
200 | d->dv_used_prev = NULL; | |
201 | ||
202 | hash_init(&d->dv_hashtab); | |
203 | d->dv_lock = 0; | |
204 | --- 6234,6245 ---- | |
205 | d = (dict_T *)alloc(sizeof(dict_T)); | |
206 | if (d != NULL) | |
207 | { | |
208 | ! /* Add the list to the list of dicts for garbage collection. */ | |
209 | if (first_dict != NULL) | |
210 | first_dict->dv_used_prev = d; | |
211 | d->dv_used_next = first_dict; | |
212 | d->dv_used_prev = NULL; | |
213 | + first_dict = d; | |
214 | ||
215 | hash_init(&d->dv_hashtab); | |
216 | d->dv_lock = 0; | |
217 | *************** | |
218 | *** 6245,6252 **** | |
219 | dict_unref(d) | |
220 | dict_T *d; | |
221 | { | |
222 | ! if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0) | |
223 | ! dict_free(d); | |
224 | } | |
225 | ||
226 | /* | |
227 | --- 6257,6264 ---- | |
228 | dict_unref(d) | |
229 | dict_T *d; | |
230 | { | |
231 | ! if (d != NULL && --d->dv_refcount <= 0) | |
232 | ! dict_free(d, TRUE); | |
233 | } | |
234 | ||
235 | /* | |
236 | *************** | |
237 | *** 6254,6269 **** | |
238 | * Ignores the reference count. | |
239 | */ | |
240 | static void | |
241 | ! dict_free(d) | |
242 | ! dict_T *d; | |
243 | { | |
244 | int todo; | |
245 | hashitem_T *hi; | |
246 | dictitem_T *di; | |
247 | ||
248 | - /* Avoid that recursive reference to the dict frees us again. */ | |
249 | - d->dv_refcount = DEL_REFCOUNT; | |
250 | - | |
251 | /* Remove the dict from the list of dicts for garbage collection. */ | |
252 | if (d->dv_used_prev == NULL) | |
253 | first_dict = d->dv_used_next; | |
254 | --- 6266,6279 ---- | |
255 | * Ignores the reference count. | |
256 | */ | |
257 | static void | |
258 | ! dict_free(d, recurse) | |
259 | ! dict_T *d; | |
260 | ! int recurse; /* Free Lists and Dictionaries recursively. */ | |
261 | { | |
262 | int todo; | |
263 | hashitem_T *hi; | |
264 | dictitem_T *di; | |
265 | ||
266 | /* Remove the dict from the list of dicts for garbage collection. */ | |
267 | if (d->dv_used_prev == NULL) | |
268 | first_dict = d->dv_used_next; | |
269 | *************** | |
270 | *** 6283,6289 **** | |
271 | * something recursive causing trouble. */ | |
272 | di = HI2DI(hi); | |
273 | hash_remove(&d->dv_hashtab, hi); | |
274 | ! dictitem_free(di); | |
275 | --todo; | |
276 | } | |
277 | } | |
278 | --- 6293,6302 ---- | |
279 | * something recursive causing trouble. */ | |
280 | di = HI2DI(hi); | |
281 | hash_remove(&d->dv_hashtab, hi); | |
282 | ! if (recurse || (di->di_tv.v_type != VAR_LIST | |
283 | ! && di->di_tv.v_type != VAR_DICT)) | |
284 | ! clear_tv(&di->di_tv); | |
285 | ! vim_free(di); | |
286 | --todo; | |
287 | } | |
288 | } | |
289 | *************** | |
290 | *** 6734,6740 **** | |
291 | EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); | |
292 | failret: | |
293 | if (evaluate) | |
294 | ! dict_free(d); | |
295 | return FAIL; | |
296 | } | |
297 | ||
298 | --- 6747,6753 ---- | |
299 | EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); | |
300 | failret: | |
301 | if (evaluate) | |
302 | ! dict_free(d, TRUE); | |
303 | return FAIL; | |
304 | } | |
305 | ||
306 | *** ../vim-7.0.134/src/proto/eval.pro Fri Mar 24 23:16:28 2006 | |
307 | --- src/proto/eval.pro Sun Oct 15 22:08:11 2006 | |
308 | *************** | |
309 | *** 44,50 **** | |
310 | extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx)); | |
311 | extern list_T *list_alloc __ARGS((void)); | |
312 | extern void list_unref __ARGS((list_T *l)); | |
313 | ! extern void list_free __ARGS((list_T *l)); | |
314 | extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); | |
315 | extern int list_append_dict __ARGS((list_T *list, dict_T *dict)); | |
316 | extern int garbage_collect __ARGS((void)); | |
317 | --- 44,50 ---- | |
318 | extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx)); | |
319 | extern list_T *list_alloc __ARGS((void)); | |
320 | extern void list_unref __ARGS((list_T *l)); | |
321 | ! extern void list_free __ARGS((list_T *l, int recurse)); | |
322 | extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); | |
323 | extern int list_append_dict __ARGS((list_T *list, dict_T *dict)); | |
324 | extern int garbage_collect __ARGS((void)); | |
325 | *** ../vim-7.0.134/src/tag.c Sun Sep 10 13:56:06 2006 | |
326 | --- src/tag.c Sun Oct 15 21:44:56 2006 | |
327 | *************** | |
328 | *** 911,917 **** | |
329 | ||
330 | set_errorlist(curwin, list, ' '); | |
331 | ||
332 | ! list_free(list); | |
333 | ||
334 | cur_match = 0; /* Jump to the first tag */ | |
335 | } | |
336 | --- 911,917 ---- | |
337 | ||
338 | set_errorlist(curwin, list, ' '); | |
339 | ||
340 | ! list_free(list, TRUE); | |
341 | ||
342 | cur_match = 0; /* Jump to the first tag */ | |
343 | } | |
344 | *** ../vim-7.0.134/src/version.c Sun Oct 15 15:10:08 2006 | |
345 | --- src/version.c Sun Oct 15 22:01:53 2006 | |
346 | *************** | |
347 | *** 668,669 **** | |
348 | --- 668,671 ---- | |
349 | { /* Add new patch number below this line */ | |
350 | + /**/ | |
351 | + 135, | |
352 | /**/ | |
353 | ||
354 | -- | |
355 | Well, you come from nothing, you go back to nothing... What have you | |
356 | lost? Nothing! | |
357 | -- Monty Python: The life of Brian | |
358 | ||
359 | /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ | |
360 | /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ | |
361 | \\\ download, build and distribute -- http://www.A-A-P.org /// | |
362 | \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |