Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-08-02 11:16:44 +0300
committerThomas Dinges <blender@dingto.org>2022-08-02 11:16:44 +0300
commitbc9d461ab0e178c45f681ee4154b97e94fa45156 (patch)
tree5c6862be58b4edf1b95e183d0f365f255d720f08
parent41689bb310469d85d9eae59ca578f4a15dc0e80b (diff)
Fix Python SystemExit exceptions silently exiting
Any script that raised a SystemExit called by --python, --python-expr command line args or by executing the text block would exit without printing a message. This caused the error from T99966 to be hidden. Add explicit handling for SystemExit to ensure the message is always shown before exiting. More details noted in code-comments.
-rw-r--r--source/blender/python/generic/py_capi_utils.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 9824d5f17c4..44293759672 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -591,6 +591,36 @@ void PyC_Err_PrintWithFunc(PyObject *py_func)
/** \name Exception Buffer Access
* \{ */
+static void pyc_exception_buffer_handle_system_exit(PyObject *error_type,
+ PyObject *error_value,
+ PyObject *error_traceback)
+{
+ if (!PyErr_GivenExceptionMatches(error_type, PyExc_SystemExit)) {
+ return;
+ }
+ /* Inspecting, follow Python's logic in #_Py_HandleSystemExit & treat as a regular exception. */
+ if (_Py_GetConfig()->inspect) {
+ return;
+ }
+
+ /* NOTE(@campbellbarton): A `SystemExit` exception will exit immediately (unless inspecting).
+ * So print the error and exit now. This is necessary as the call to #PyErr_Print exits,
+ * the temporary `sys.stderr` assignment causes the output to be suppressed, failing silently.
+ * Instead, restore the error and print it. If Python changes it's behavior and doesn't exit in
+ * the future - continue to create the exception buffer, see: T99966.
+ *
+ * Arguably accessing a `SystemExit` exception as a buffer should be supported without exiting.
+ * (by temporarily enabling inspection for example) however - it's not obvious exactly when this
+ * should be enabled and complicates the Python API by introducing different kinds of execution.
+ * Since the rule of thumb is for Blender's embedded Python to match stand-alone Python,
+ * favor exiting when a `SystemExit` is raised.
+ * Especially since this exception more likely to be used for background/batch-processing
+ * utilities where exiting immediately makes sense, the possibility of this being called
+ * indirectly from python-drivers or modal-operators is less of a concern. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_Print();
+}
+
/* returns the exception string as a new PyUnicode object, depends on external traceback module */
# if 0
@@ -641,6 +671,8 @@ PyObject *PyC_ExceptionBuffer(void)
PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ pyc_exception_buffer_handle_system_exit(error_type, error_value, error_traceback);
+
PyErr_Clear();
/* import io
@@ -713,6 +745,11 @@ PyObject *PyC_ExceptionBuffer_Simple(void)
return NULL;
}
+ /* Since #PyErr_Print is not called it's not essential that `SystemExit` exceptions are handled.
+ * Do this to match the behavior of #PyC_ExceptionBuffer since requesting a brief exception
+ * shouldn't result in completely different behavior. */
+ pyc_exception_buffer_handle_system_exit(error_type, error_value, error_traceback);
+
if (PyErr_GivenExceptionMatches(error_type, PyExc_SyntaxError)) {
/* Special exception for syntax errors,
* in these cases the full error is verbose and not very useful,