[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [39006] trunk/blender/source/blender/ python/intern: fix [#28114] Render Crash

Campbell Barton ideasman42 at gmail.com
Thu Aug 4 03:56:41 CEST 2011


Revision: 39006
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=39006
Author:   campbellbarton
Date:     2011-08-04 01:56:36 +0000 (Thu, 04 Aug 2011)
Log Message:
-----------
fix [#28114] Render Crash

existing check for driver to use GIL was not thread safe and could cause, details in the report.

This bug was caused by a check to avoid hanging, a fix for [#27683] that worked in 2.4x because the UI didn't use python to draw while rendering.

Apply a different fix for [#27683], when calling an operator, call PyEval_SaveThread(), then PyEval_RestoreThread() so the GIL can be aquired by threads started by the operator - in this case bake starting a thread that evaluates drivers.

Modified Paths:
--------------
    trunk/blender/source/blender/python/intern/bpy_driver.c
    trunk/blender/source/blender/python/intern/bpy_operator.c

Modified: trunk/blender/source/blender/python/intern/bpy_driver.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_driver.c	2011-08-03 22:26:59 UTC (rev 39005)
+++ trunk/blender/source/blender/python/intern/bpy_driver.c	2011-08-04 01:56:36 UTC (rev 39006)
@@ -41,8 +41,6 @@
 
 #include "bpy_driver.h"
 
-#include "../generic/py_capi_utils.h"
-
 /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
 PyObject *bpy_pydriver_Dict= NULL;
 
@@ -89,7 +87,7 @@
 void BPY_driver_reset(void)
 {
 	PyGILState_STATE gilstate;
-	int use_gil= !PYC_INTERPRETER_ACTIVE;
+	int use_gil= 1; /* !PYC_INTERPRETER_ACTIVE; */
 
 	if(use_gil)
 		gilstate= PyGILState_Ensure();
@@ -120,9 +118,14 @@
 /* This evals py driver expressions, 'expr' is a Python expression that
  * should evaluate to a float number, which is returned.
  *
- * note: PyGILState_Ensure() isnt always called because python can call the
- * bake operator which intern starts a thread which calls scene update which
- * does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE if PyGILState_Ensure() is needed.
+ * (old)note: PyGILState_Ensure() isnt always called because python can call
+ * the bake operator which intern starts a thread which calls scene update
+ * which does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE
+ * if PyGILState_Ensure() is needed - see [#27683]
+ *
+ * (new)note: checking if python is running is not threadsafe [#28114]
+ * now release the GIL on python operator execution instead, using
+ * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender.
  */
 float BPY_driver_exec(ChannelDriver *driver)
 {
@@ -149,7 +152,7 @@
 		return 0.0f;
 	}
 
-	use_gil= !PYC_INTERPRETER_ACTIVE;
+	use_gil= 1; /* !PYC_INTERPRETER_ACTIVE; */
 
 	if(use_gil)
 		gilstate= PyGILState_Ensure();

Modified: trunk/blender/source/blender/python/intern/bpy_operator.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_operator.c	2011-08-03 22:26:59 UTC (rev 39005)
+++ trunk/blender/source/blender/python/intern/bpy_operator.c	2011-08-04 01:56:36 UTC (rev 39006)
@@ -55,6 +55,10 @@
 #include "BKE_report.h"
 #include "BKE_context.h"
 
+/* so operators called can spawn threads which aquire the GIL */
+#define BPY_RELEASE_GIL
+
+
 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
 {
 	wmOperatorType *ot;
@@ -219,8 +223,23 @@
 			reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
 			BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these dont move into global reports */
 
-			operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
+#ifdef BPY_RELEASE_GIL
+			/* release GIL, since a thread could be started from an operator
+			 * that updates a driver */
+			/* note: I havve not seen any examples of code that does this
+			 * so it may not be officially supported but seems to work ok. */
+			{
+				PyThreadState *ts= PyEval_SaveThread();
+#endif
 
+				operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
+
+#ifdef BPY_RELEASE_GIL
+				/* regain GIL */
+				PyEval_RestoreThread(ts);
+			}
+#endif
+
 			error_val= BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE);
 
 			/* operator output is nice to have in the terminal/console too */




More information about the Bf-blender-cvs mailing list