fix [#28672] Blender segfault after exiting a game that was opened with
authorCampbell Barton <ideasman42@gmail.com>
Tue, 20 Sep 2011 12:22:19 +0000 (12:22 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 20 Sep 2011 12:22:19 +0000 (12:22 +0000)
autoplay on (Blender, not blenderplayer)

blender now stops the sound system and free's its self on Pythons
sys.exit().

source/blender/python/intern/CMakeLists.txt
source/blender/python/intern/bpy.h
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_interface_atexit.c [new file with mode: 0644]
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_init_exit.c

index 9ed0859..acdee53 100644 (file)
@@ -47,6 +47,7 @@ set(SRC
        bpy_app_handlers.c
        bpy_driver.c
        bpy_interface.c
+       bpy_interface_atexit.c
        bpy_intern_string.c
        bpy_library.c
        bpy_operator.c
index 0ebc6bb..6844d66 100644 (file)
@@ -28,3 +28,6 @@
  
 void BPy_init_modules(void);
 extern PyObject *bpy_package_py;
+
+/* bpy_interface_atexit.c */
+void BPY_atexit_init(void);
index e5bfc1d..87edf93 100644 (file)
@@ -30,7 +30,7 @@
  
 /* grr, python redefines */
 #ifdef _POSIX_C_SOURCE
-#undef _POSIX_C_SOURCE
+#  undef _POSIX_C_SOURCE
 #endif
 
 #include <Python.h>
@@ -241,6 +241,8 @@ void BPY_python_start(int argc, const char **argv)
        
        pyrna_alloc_types();
 
+       BPY_atexit_init(); /* this can init any time */
+
 #ifndef WITH_PYTHON_MODULE
        py_tstate= PyGILState_GetThisThreadState();
        PyEval_ReleaseThread(py_tstate);
diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c
new file mode 100644 (file)
index 0000000..0230a3b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_interface_atexit.c
+ *  \ingroup pythonintern
+ */
+
+
+#include <Python.h>
+
+#include "bpy_util.h"
+
+#include "WM_api.h"
+
+#include "BLI_utildefines.h"
+
+static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw))
+{
+       /* close down enough of blender at least not to crash */
+       struct bContext *C= BPy_GetContext();
+
+       WM_exit_ext(C, 0);
+
+       Py_RETURN_NONE;
+}
+
+static PyMethodDef meth_bpy_atexit= {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL};
+
+void BPY_atexit_init(void)
+{
+       /* note - no error checking, if any of these fail we'll get a crash
+        * this is intended, but if its problematic it could be changed
+        * - campbell */
+
+       PyObject *atexit_mod= PyImport_ImportModuleLevel((char *)"atexit", NULL, NULL, NULL, 0);
+       PyObject *atexit_register= PyObject_GetAttrString(atexit_mod, "register");
+       PyObject *args= PyTuple_New(1);
+       PyObject *ret;
+
+       PyTuple_SET_ITEM(args, 0, (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL));
+
+       ret= PyObject_CallObject(atexit_register, args);
+
+       Py_DECREF(atexit_mod);
+       Py_DECREF(atexit_register);
+       Py_DECREF(args);
+
+       if(ret) {
+               Py_DECREF(ret);
+       }
+       else { /* should never happen */
+               PyErr_Print();
+       }
+
+}
index 5bdf1ec..9e19a05 100644 (file)
@@ -72,6 +72,7 @@ void          WM_setinitialstate_fullscreen(void);
 void           WM_setinitialstate_normal(void);
 
 void           WM_init                         (struct bContext *C, int argc, const char **argv);
+void           WM_exit_ext                     (struct bContext *C, const short do_python);
 void           WM_exit                         (struct bContext *C);
 void           WM_main                         (struct bContext *C);
 
index 3653015..837b7eb 100644 (file)
@@ -342,7 +342,8 @@ extern void free_fmodifiers_copybuf(void);
 extern void free_posebuf(void); 
 
 /* called in creator.c even... tsk, split this! */
-void WM_exit(bContext *C)
+/* note, doesnt run exit() call WM_exit() for that */
+void WM_exit_ext(bContext *C, const short do_python)
 {
        wmWindow *win;
 
@@ -408,14 +409,17 @@ void WM_exit(bContext *C)
        
 
 #ifdef WITH_PYTHON
-       /* XXX - old note */
-       /* before free_blender so py's gc happens while library still exists */
-       /* needed at least for a rare sigsegv that can happen in pydrivers */
-
-       /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's
-        * so decref'ing them after python ends causes bad problems every time
-        * the pyDriver bug can be fixed if it happens again we can deal with it then */
-       BPY_python_end();
+       /* option not to close python so we can use 'atexit' */
+       if(do_python) {
+               /* XXX - old note */
+               /* before free_blender so py's gc happens while library still exists */
+               /* needed at least for a rare sigsegv that can happen in pydrivers */
+
+               /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's
+                * so decref'ing them after python ends causes bad problems every time
+                * the pyDriver bug can be fixed if it happens again we can deal with it then */
+               BPY_python_end();
+       }
 #endif
 
        GPU_global_buffer_pool_free();
@@ -460,6 +464,10 @@ void WM_exit(bContext *C)
                getchar();
        }
 #endif 
-       exit(G.afbreek==1);
 }
 
+void WM_exit(bContext *C)
+{
+       WM_exit_ext(C, 1);
+       exit(G.afbreek==1);
+}