Fix T37698: Crash from invalid context access when freeing custom

python nodes on Blender exit.

The nodeFreeNode function is calling a customizable freefunc callback,
which can be implemented by python. However, the context is invalid when
using this callback while the node tree data block is freed on exit.
Luckily it is also not necessary: When freeing the bNodeTree data blocks
all that is needed is freeing of the DNA data, no other side effects
should happen. So now disable the api callbacks when freeing nodes in
the ntreeFreeTree function.

Also some minor cleanup: checking node->typeinfo is not necessary, all
nodes will always have a valid typeinfo pointer - if a node type is
unknown this will be a stub bNodeType to avoid the need for such checks.
This commit is contained in:
Lukas Tönne 2013-12-05 15:02:17 +01:00
parent 68d39a262c
commit 193dd134da
Notes: blender-bot 2023-02-14 20:13:05 +01:00
Referenced by issue blender/blender-addons#37698, Crash on .blend unload if it contains Python nodes
1 changed files with 11 additions and 6 deletions

View File

@ -1588,14 +1588,14 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
}
/** \note caller needs to manage node->id user */
void nodeFreeNode(bNodeTree *ntree, bNode *node)
static void node_free_node_ex(bNodeTree *ntree, bNode *node, bool use_api_free_cb)
{
bNodeSocket *sock, *nextsock;
char propname_esc[MAX_IDPROP_NAME * 2];
char prefix[MAX_IDPROP_NAME * 2];
/* extra free callback */
if (node->typeinfo && node->typeinfo->freefunc_api) {
if (use_api_free_cb && node->typeinfo->freefunc_api) {
PointerRNA ptr;
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
@ -1617,7 +1617,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
BKE_animdata_fix_paths_remove((ID *)ntree, prefix);
if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
if (ntree->typeinfo->free_node_cache)
ntree->typeinfo->free_node_cache(ntree, node);
/* texture node has bad habit of keeping exec data around */
@ -1626,7 +1626,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->execdata = NULL;
}
if (node->typeinfo && node->typeinfo->freefunc)
if (node->typeinfo->freefunc)
node->typeinfo->freefunc(node);
}
@ -1654,6 +1654,11 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->update |= NTREE_UPDATE_NODES;
}
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
node_free_node_ex(ntree, node, true);
}
static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
{
if (sock->prop) {
@ -1736,7 +1741,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
(void)do_id_user;
#endif
nodeFreeNode(ntree, node);
node_free_node_ex(ntree, node, false);
}
/* free interface sockets */
@ -2507,7 +2512,7 @@ void BKE_node_clipboard_clear(void)
for (node = node_clipboard.nodes.first; node; node = node_next) {
node_next = node->next;
nodeFreeNode(NULL, node);
node_free_node_ex(NULL, node, false);
}
node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;