If an error happens outside any protected environment, Lua calls a panic function (see lua_atpanic) and then calls abort, thus exiting the host application. Your panic function can avoid this exit by never returning (e.g., doing a long jump to your own recovery point outside Lua).
static PyObject *
_cffi_f_lua_pushboolean(PyObject *self, PyObject *args){ lua_State * x0; int x1; Py_ssize_t datasize; PyObject *arg0; PyObject *arg1;
if (!PyArg_UnpackTuple(args, "lua_pushboolean", 2, 2, &arg0, &arg1)) return NULL;
datasize = _cffi_prepare_pointer_call_argument( _cffi_type(8), arg0, (char **)&x0); if (datasize != 0) { if (datasize < 0) return NULL; x0 = (lua_State *)alloca((size_t)datasize); memset((void *)x0, 0, (size_t)datasize); if (_cffi_convert_array_from_object((char *)x0, _cffi_type(8), arg0) < 0) return NULL; }
x1 = _cffi_to_c_int(arg1, int); if (x1 == (int)-1 && PyErr_Occurred()) return NULL;
Py_BEGIN_ALLOW_THREADS _cffi_restore_errno(); { lua_pushboolean(x0, x1); } _cffi_save_errno(); Py_END_ALLOW_THREADS
(void)self; /* unused */ Py_INCREF(Py_None); return Py_None;}
PyThreadState *_save;
if (setjmp(global_env) == 0){
_save = PyEval_SaveThread(); _cffi_restore_errno(); { lua_pushboolean(x0, x1); } _cffi_save_errno(); PyEval_RestoreThread(_save);
}else{
_cffi_save_errno(); PyEval_RestoreThread(_save);
PyErr_SetString(...);
}
static void awd(void){ PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyErr_SetString(PyExc_RuntimeError, "awd"); PyGILState_Release(gstate);}
>>> lib.awd()RuntimeError: awd
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "<stdin>", line 1, in <module>SystemError: <built-in method awd of CompiledLib object at 0x7f572cbe7278> returned a result with an error set
--- a/recompiler.py+++ b/recompiler.py@@ -722,6 +722,7 @@ class Recompiler: prnt(' (void)self; /* unused */') if numargs == 0: prnt(' (void)noarg; /* unused */')+ prnt(' if(PyErr_Occurred()) return NULL;') if result_code: prnt(' return %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type'))
>>> lib.awd()Traceback (most recent call last): File "<stdin>", line 1, in <module>RuntimeError: awd
>>>> lib.awd()RPython traceback: File "pypy_module_cpyext.c", line 17127, in wrapper_second_level__star_2_6 File "pypy_module_cpyext_1.c", line 37175, in from_refFatal RPython error: AssertionErrorAborted (core dumped)
#define Py_LIMITED_API#include <Python.h>static void voidfunc(void){}static PyObject* with_gil(PyObject *self, PyObject *args){ Py_BEGIN_ALLOW_THREADS {voidfunc();} Py_END_ALLOW_THREADS Py_XINCREF(Py_None); return Py_None;}static PyObject* without_gil(PyObject *self, PyObject *args){ voidfunc(); Py_XINCREF(Py_None); return Py_None;}static PyMethodDef meths[] = { {"with_gil", with_gil, METH_NOARGS, "with gil"}, {"without_gil", without_gil, METH_NOARGS, "without gil"}, {0, 0, 0, 0}};static struct PyModuleDef mod = { PyModuleDef_HEAD_INIT, "gilbrench", 0, -1, meths};PyMODINIT_FUNCPyInit_gilbrench(void){ return PyModule_Create(&mod);}
>>> timeit.timeit('func()', globals={'func':gilbrench.without_gil}, number=10**9)32.65148849999969>>> timeit.timeit('func()', globals={'func':gilbrench.with_gil}, number=10**9)
37.30776556799901