[Bf-blender-cvs] [ad8add5f0cb] master: Fix T98427: Crash adding quick effects smoke from Python

Campbell Barton noreply at git.blender.org
Fri Jun 24 15:30:06 CEST 2022


Commit: ad8add5f0cbe1b5abb85a6cf510e52b66de273e9
Author: Campbell Barton
Date:   Fri Jun 24 23:28:19 2022 +1000
Branches: master
https://developer.blender.org/rBad8add5f0cbe1b5abb85a6cf510e52b66de273e9

Fix T98427: Crash adding quick effects smoke from Python

Manta flow used the `__main__` namespace which it was executed in,
this caused a bug when calculating fluid from Python, which clears
it's `__main__` name-space after execution.
This caused Manta-flows name space to be cleared too.

Resolve this by creating a separate name-space for manta-flow.

Reviewed by: SonnyCampbell_Unity

Ref D15269

===================================================================

M	extern/mantaflow/helper/pwrapper/registry.cpp
M	extern/mantaflow/helper/pwrapper/registry.h
M	intern/mantaflow/intern/MANTA_main.cpp

===================================================================

diff --git a/extern/mantaflow/helper/pwrapper/registry.cpp b/extern/mantaflow/helper/pwrapper/registry.cpp
index 5196c0409f8..b20651f3baa 100644
--- a/extern/mantaflow/helper/pwrapper/registry.cpp
+++ b/extern/mantaflow/helper/pwrapper/registry.cpp
@@ -115,7 +115,7 @@ class WrapperRegistry {
   void construct(const std::string &scriptname, const vector<string> &args);
   void cleanup();
   void renameObjects();
-  void runPreInit();
+  void runPreInit(PyObject *name_space);
   PyObject *initModule();
   ClassData *lookup(const std::string &name);
   bool canConvert(ClassData *from, ClassData *to);
@@ -505,7 +505,7 @@ void WrapperRegistry::addConstants(PyObject *module)
   }
 }
 
-void WrapperRegistry::runPreInit()
+void WrapperRegistry::runPreInit(PyObject *name_space)
 {
   // add python directories to path
   PyObject *sys_path = PySys_GetObject((char *)"path");
@@ -518,7 +518,15 @@ void WrapperRegistry::runPreInit()
   }
   if (!mCode.empty()) {
     mCode = "from manta import *\n" + mCode;
-    PyRun_SimpleString(mCode.c_str());
+    PyObject *return_value = PyRun_String(mCode.c_str(), Py_file_input, name_space, name_space);
+    if (return_value == nullptr) {
+      if (PyErr_Occurred()) {
+        PyErr_Print();
+      }
+    }
+    else {
+      Py_DECREF(return_value);
+    }
   }
 }
 
@@ -698,11 +706,11 @@ PyObject *WrapperRegistry::initModule()
 //******************************************************
 // Register members and exposed functions
 
-void setup(const std::string &filename, const std::vector<std::string> &args)
+void setup(const std::string &filename, const std::vector<std::string> &args, PyObject *name_space)
 {
   WrapperRegistry::instance().construct(filename, args);
   Py_Initialize();
-  WrapperRegistry::instance().runPreInit();
+  WrapperRegistry::instance().runPreInit(name_space);
 }
 
 void finalize()
diff --git a/extern/mantaflow/helper/pwrapper/registry.h b/extern/mantaflow/helper/pwrapper/registry.h
index d9d2bbb624b..aa63383515f 100644
--- a/extern/mantaflow/helper/pwrapper/registry.h
+++ b/extern/mantaflow/helper/pwrapper/registry.h
@@ -48,7 +48,7 @@ template<class T> struct Namify {
 namespace Pb {
 
 // internal registry access
-void setup(const std::string &filename, const std::vector<std::string> &args);
+void setup(const std::string &filename, const std::vector<std::string> &args, PyObject *name_space);
 void finalize();
 bool canConvert(PyObject *obj, const std::string &to);
 Manta::PbClass *objFromPy(PyObject *obj);
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 282fbdb3f77..000bc313ab1 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -567,10 +567,53 @@ MANTA::~MANTA()
 }
 
 /**
- * Store a pointer to the __main__ module used by mantaflow. This is necessary, because sometimes
- * Blender will overwrite that module. That happens when e.g. scripts are executed in the text
- * editor.
- *
+ * Copied from `PyC_DefaultNameSpace` in Blender.
+ * with some differences:
+ * - Doesn't touch `sys.modules`, use #manta_python_main_module_activate instead.
+ * - Returns the module instead of the modules `dict`.
+ * */
+static PyObject *manta_python_main_module_create(const char *filename)
+{
+  PyObject *builtins = PyEval_GetBuiltins();
+  PyObject *mod_main = PyModule_New("__main__");
+  PyModule_AddStringConstant(mod_main, "__name__", "__main__");
+  if (filename) {
+    /* __file__ mainly for nice UI'ness
+     * NOTE: this won't map to a real file when executing text-blocks and buttons. */
+    PyModule_AddObject(mod_main, "__file__", PyUnicode_InternFromString(filename));
+  }
+  PyModule_AddObject(mod_main, "__builtins__", builtins);
+  Py_INCREF(builtins); /* AddObject steals a reference */
+  return mod_main;
+}
+
+static void manta_python_main_module_activate(PyObject *mod_main)
+{
+  PyObject *modules = PyImport_GetModuleDict();
+  PyObject *main_mod_cmp = PyDict_GetItemString(modules, "__main__");
+  if (mod_main == main_mod_cmp) {
+    return;
+  }
+  /* NOTE: we could remove the reference to `mod_main` here, but as it's know to be removed
+   * accept that there is temporarily an extra reference. */
+  PyDict_SetItemString(modules, "__main__", mod_main);
+}
+
+static void manta_python_main_module_backup(PyObject **r_main_mod)
+{
+  PyObject *modules = PyImport_GetModuleDict();
+  *r_main_mod = PyDict_GetItemString(modules, "__main__");
+  Py_XINCREF(*r_main_mod); /* don't free */
+}
+
+static void manta_python_main_module_restore(PyObject *main_mod)
+{
+  PyObject *modules = PyImport_GetModuleDict();
+  PyDict_SetItemString(modules, "__main__", main_mod);
+  Py_XDECREF(main_mod);
+}
+
+/**
  * Mantaflow stores many variables in the globals() dict of the __main__ module. To be able to
  * access these variables, the same __main__ module has to be used every time.
  *
@@ -579,14 +622,35 @@ MANTA::~MANTA()
  */
 static PyObject *manta_main_module = nullptr;
 
+static void manta_python_main_module_clear()
+{
+  if (manta_main_module) {
+    Py_DECREF(manta_main_module);
+    manta_main_module = nullptr;
+  }
+}
+
+static PyObject *manta_python_main_module_ensure()
+{
+  if (!manta_main_module) {
+    manta_main_module = manta_python_main_module_create("<manta_namespace>");
+  }
+  return manta_main_module;
+}
+
 bool MANTA::runPythonString(vector<string> commands)
 {
   bool success = true;
   PyGILState_STATE gilstate = PyGILState_Ensure();
 
-  if (manta_main_module == nullptr) {
-    manta_main_module = PyImport_ImportModule("__main__");
-  }
+  /* Temporarily set `sys.modules["__main__"]` as some Python modules expect this. */
+  PyObject *main_mod_backup;
+  manta_python_main_module_backup(&main_mod_backup);
+
+  /* If we never want to run this when the module isn't initialize,
+   * assign with `manta_python_main_module_ensure()`. */
+  BLI_assert(manta_main_module != nullptr);
+  manta_python_main_module_activate(manta_main_module);
 
   for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) {
     string command = *it;
@@ -605,6 +669,9 @@ bool MANTA::runPythonString(vector<string> commands)
       Py_DECREF(return_value);
     }
   }
+
+  manta_python_main_module_restore(main_mod_backup);
+
   PyGILState_Release(gilstate);
 
   BLI_assert(success);
@@ -622,7 +689,10 @@ void MANTA::initializeMantaflow()
   /* Initialize extension classes and wrappers. */
   srand(0);
   PyGILState_STATE gilstate = PyGILState_Ensure();
-  Pb::setup(filename, fill); /* Namespace from Mantaflow (registry). */
+
+  PyObject *manta_main_module = manta_python_main_module_ensure();
+  PyObject *globals_dict = PyModule_GetDict(manta_main_module);
+  Pb::setup(filename, fill, globals_dict); /* Namespace from Mantaflow (registry). */
   PyGILState_Release(gilstate);
 }
 
@@ -633,6 +703,7 @@ void MANTA::terminateMantaflow()
 
   PyGILState_STATE gilstate = PyGILState_Ensure();
   Pb::finalize(); /* Namespace from Mantaflow (registry). */
+  manta_python_main_module_clear();
   PyGILState_Release(gilstate);
 }



More information about the Bf-blender-cvs mailing list