entry-directories: don't modify a list while iterating it
cached_dir_unref() tries to remove the directory from the parent's
list of subdirectories, but it is also called when the parent is
being freed and iterating with foreach() on its directory list.
This is unsafe, so don't do it.
Also, fix the logic for remove_subdir() to unref() only when it's
right to do so (ie, always, when the function is called, because
everything keeps strong references).
https://bugzilla.gnome.org/show_bug.cgi?id=720460
Giovanni Campagna authored 10 years ago
Clement Lefebvre committed 6 years ago
83 | 83 | static gboolean cached_dir_load_entries_recursive (CachedDir *dir, |
84 | 84 | const char *dirname); |
85 | 85 | static void cached_dir_unref (CachedDir *dir); |
86 | static void cached_dir_unref_noparent (CachedDir *dir); | |
86 | 87 | static CachedDir * cached_dir_add_subdir (CachedDir *dir, |
87 | 88 | const char *basename, |
88 | 89 | const char *path); |
156 | 157 | dir->entries = NULL; |
157 | 158 | |
158 | 159 | g_slist_foreach (dir->subdirs, |
159 | (GFunc) cached_dir_unref, | |
160 | (GFunc) cached_dir_unref_noparent, | |
160 | 161 | NULL); |
161 | 162 | g_slist_free (dir->subdirs); |
162 | 163 | dir->subdirs = NULL; |
187 | 188 | if (parent != NULL) |
188 | 189 | cached_dir_remove_subdir (parent, dir->name); |
189 | 190 | |
191 | if (dir->notify) | |
192 | dir->notify (dir, dir->notify_data); | |
193 | ||
194 | cached_dir_free (dir); | |
195 | } | |
196 | } | |
197 | ||
198 | static void | |
199 | cached_dir_unref_noparent (CachedDir *dir) | |
200 | { | |
201 | if (--dir->references == 0) | |
202 | { | |
190 | 203 | if (dir->notify) |
191 | 204 | dir->notify (dir, dir->notify_data); |
192 | 205 | |
419 | 432 | { |
420 | 433 | subdir->deleted = TRUE; |
421 | 434 | |
422 | if (subdir->references == 0) | |
423 | { | |
424 | cached_dir_unref (subdir); | |
425 | dir->subdirs = g_slist_remove (dir->subdirs, subdir); | |
426 | } | |
435 | cached_dir_unref (subdir); | |
436 | dir->subdirs = g_slist_remove (dir->subdirs, subdir); | |
427 | 437 | |
428 | 438 | return TRUE; |
429 | 439 | } |