Commit fc794431 authored by Stefan Behnel's avatar Stefan Behnel

allow "unraisable" warnings in nogil functions

parent 3e601053
......@@ -2071,7 +2071,7 @@ class CCodeWriter(object):
self.funcstate.uses_error_indicator = True
self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple)
def put_unraisable(self, qualified_name):
def put_unraisable(self, qualified_name, nogil=False):
"""
Generate code to print a Python warning for an unraisable exception.
......@@ -2082,10 +2082,11 @@ class CCodeWriter(object):
Naming.clineno_cname,
Naming.lineno_cname,
Naming.filename_cname,
int(self.globalstate.directives['unraisable_tracebacks'])
self.globalstate.directives['unraisable_tracebacks'],
nogil,
)
self.funcstate.uses_error_indicator = True
self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %s);' % format_tuple)
self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %d, %d);' % format_tuple)
self.globalstate.use_utility_code(
UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
......
......@@ -1961,7 +1961,7 @@ class FuncDefNode(StatNode, BlockNode):
warning(self.entry.pos,
"Unraisable exception in function '%s'." %
self.entry.qualified_name, 0)
code.put_unraisable(self.entry.qualified_name)
code.put_unraisable(self.entry.qualified_name, lenv.nogil)
default_retval = self.return_type.default_value
if err_val is None and default_retval:
err_val = default_retval
......
......@@ -410,16 +410,21 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
static void __Pyx_WriteUnraisable(const char *name, int clineno,
int lineno, const char *filename,
int full_traceback); /*proto*/
int full_traceback, int nogil); /*proto*/
/////////////// WriteUnraisableException ///////////////
//@requires: PyErrFetchRestore
static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
int full_traceback) {
int full_traceback, CYTHON_UNUSED int nogil) {
PyObject *old_exc, *old_val, *old_tb;
PyObject *ctx;
#ifdef WITH_THREAD
PyGILState_STATE state;
if (nogil)
state = PyGILState_Ensure();
#endif
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
if (full_traceback) {
Py_XINCREF(old_exc);
......@@ -440,6 +445,10 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
PyErr_WriteUnraisable(ctx);
Py_DECREF(ctx);
}
#ifdef WITH_THREAD
if (nogil)
PyGILState_Release(state);
#endif
}
/////////////// AddTraceback.proto ///////////////
......
# mode: run
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
def test(int x):
"""
>>> test(5)
......@@ -35,3 +43,23 @@ def test_nogil_exception_propagation():
"""
with nogil:
nogil_func()
cdef int write_unraisable() nogil:
with gil:
raise ValueError()
def test_unraisable():
"""
>>> print(test_unraisable()) # doctest: +ELLIPSIS
Exception...ignored...
"""
import sys
old_stderr = sys.stderr
stderr = sys.stderr = StringIO()
try:
write_unraisable()
finally:
sys.stderr = old_stderr
return stderr.getvalue().strip()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment