Fix T49553: Blender 2.78 crashes when File->Data Previews ->Refresh Datablock Previews

New recursive iteration over IDs in BKE_library_foreach_ID_link() was
broken by the infamous nodetree case. We cannot really recusively call
this function in that case, so better to deffer handling of
non-datablock NodeTrees as if real IDs here.

Also fixed initial ID not being stored as handled, in rare cases this
could also lead to infinite looping.

To be backported to 2.78a.
This commit is contained in:
Bastien Montagne 2016-10-04 15:03:34 +02:00
parent b4f9766ed1
commit e5c3284467
Notes: blender-bot 2023-02-14 07:32:42 +01:00
Referenced by issue #49553, Blender 2.78 crashes when File->Data Previews ->Refresh Datablock Previews
1 changed files with 23 additions and 6 deletions

View File

@ -264,6 +264,21 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
FOREACH_FINALIZE_VOID;
}
static void library_foreach_ID_as_subdata_link(
ID *id, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
if (flag & IDWALK_RECURSE) {
/* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in IDWALK_RECURSE case is
* troublesome, see T49553. */
if (!BLI_gset_haskey(data->ids_handled, id)) {
BLI_gset_add(data->ids_handled, id);
BLI_LINKSTACK_PUSH(data->ids_todo, id);
}
}
else {
BKE_library_foreach_ID_link(id, callback, user_data, flag);
}
}
/**
* Loop over all of the ID's this datablock links to.
@ -281,6 +296,8 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
data.ids_handled = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
BLI_LINKSTACK_INIT(data.ids_todo);
BLI_gset_add(data.ids_handled, id);
}
else {
data.ids_handled = NULL;
@ -325,7 +342,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(scene->clip, IDWALK_USER);
if (scene->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)scene->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)scene->nodetree, callback, user_data, flag, &data);
}
/* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
* since basact is just a pointer to one of those items. */
@ -589,7 +606,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (material->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)material->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)material->nodetree, callback, user_data, flag, &data);
}
CALLBACK_INVOKE(material->group, IDWALK_USER);
break;
@ -600,7 +617,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Tex *texture = (Tex *) id;
if (texture->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)texture->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)texture->nodetree, callback, user_data, flag, &data);
}
CALLBACK_INVOKE(texture->ima, IDWALK_USER);
if (texture->env) {
@ -633,7 +650,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (lamp->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)lamp->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)lamp->nodetree, callback, user_data, flag, &data);
}
break;
}
@ -673,7 +690,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (world->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)world->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)world->nodetree, callback, user_data, flag, &data);
}
break;
}
@ -817,7 +834,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (linestyle->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_link((ID *)linestyle->nodetree, callback, user_data, flag);
library_foreach_ID_as_subdata_link((ID *)linestyle->nodetree, callback, user_data, flag, &data);
}
for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {