| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup pythonintern | 
					
						
							| 
									
										
										
										
											2011-11-05 08:21:12 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-06-21 09:50:23 +10:00
										 |  |  |  * This file inserts an exit callback into Python's 'atexit' module. | 
					
						
							| 
									
										
										
										
											2011-11-05 08:21:12 +00:00
										 |  |  |  * Without this sys.exit() can crash because blender is not properly closing | 
					
						
							|  |  |  |  * resources. | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-07 05:26:12 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | #include "bpy.h" /* own include */
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "bpy_capi_utils.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* close down enough of blender at least not to crash */ | 
					
						
							| 
									
										
										
										
											2020-10-15 18:20:15 +11:00
										 |  |  |   struct bContext *C = BPY_context_get(); | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 18:34:52 +10:00
										 |  |  |   WM_exit_ex(C, false); | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | static PyMethodDef meth_bpy_atexit = {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL}; | 
					
						
							| 
									
										
										
										
											2021-02-05 16:23:34 +11:00
										 |  |  | static PyObject *func_bpy_atregister = NULL; /* borrowed reference, `atexit` holds. */ | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  | static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg) | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   /* 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 */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-17 18:30:31 +00:00
										 |  |  |   PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0); | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  |   PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name); | 
					
						
							|  |  |  |   PyObject *args = PyTuple_New(1); | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  |   PyObject *ret; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  |   PyTuple_SET_ITEM(args, 0, atexit_func_arg); | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |   Py_INCREF(atexit_func_arg); /* only incref so we don't dec'ref along with 'args' */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  |   ret = PyObject_CallObject(atexit_func, args); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  |   Py_DECREF(atexit_mod); | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  |   Py_DECREF(atexit_func); | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  |   Py_DECREF(args); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (ret) { | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  |     Py_DECREF(ret); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { /* should never happen */ | 
					
						
							|  |  |  |     PyErr_Print(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_atexit_register(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* atexit module owns this new function reference */ | 
					
						
							| 
									
										
										
										
											2011-09-20 17:07:33 +00:00
										 |  |  |   BLI_assert(func_bpy_atregister == NULL); | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  |   func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL); | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  |   atexit_func_call("register", func_bpy_atregister); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_atexit_unregister(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-20 17:07:33 +00:00
										 |  |  |   BLI_assert(func_bpy_atregister != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-20 15:17:24 +00:00
										 |  |  |   atexit_func_call("unregister", func_bpy_atregister); | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  |   func_bpy_atregister = NULL; /* don't really need to set but just in case */ | 
					
						
							| 
									
										
										
										
											2011-09-20 12:22:19 +00:00
										 |  |  | } |