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): ...@@ -2071,7 +2071,7 @@ class CCodeWriter(object):
self.funcstate.uses_error_indicator = True self.funcstate.uses_error_indicator = True
self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple) 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. Generate code to print a Python warning for an unraisable exception.
...@@ -2082,10 +2082,11 @@ class CCodeWriter(object): ...@@ -2082,10 +2082,11 @@ class CCodeWriter(object):
Naming.clineno_cname, Naming.clineno_cname,
Naming.lineno_cname, Naming.lineno_cname,
Naming.filename_cname, Naming.filename_cname,
int(self.globalstate.directives['unraisable_tracebacks']) self.globalstate.directives['unraisable_tracebacks'],
nogil,
) )
self.funcstate.uses_error_indicator = True 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( self.globalstate.use_utility_code(
UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c")) UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
......
...@@ -1961,7 +1961,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1961,7 +1961,7 @@ class FuncDefNode(StatNode, BlockNode):
warning(self.entry.pos, warning(self.entry.pos,
"Unraisable exception in function '%s'." % "Unraisable exception in function '%s'." %
self.entry.qualified_name, 0) 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 default_retval = self.return_type.default_value
if err_val is None and default_retval: if err_val is None and default_retval:
err_val = default_retval err_val = default_retval
......
...@@ -410,16 +410,21 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, ...@@ -410,16 +410,21 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
static void __Pyx_WriteUnraisable(const char *name, int clineno, static void __Pyx_WriteUnraisable(const char *name, int clineno,
int lineno, const char *filename, int lineno, const char *filename,
int full_traceback); /*proto*/ int full_traceback, int nogil); /*proto*/
/////////////// WriteUnraisableException /////////////// /////////////// WriteUnraisableException ///////////////
//@requires: PyErrFetchRestore //@requires: PyErrFetchRestore
static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, 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 *old_exc, *old_val, *old_tb;
PyObject *ctx; PyObject *ctx;
#ifdef WITH_THREAD
PyGILState_STATE state;
if (nogil)
state = PyGILState_Ensure();
#endif
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb); __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
if (full_traceback) { if (full_traceback) {
Py_XINCREF(old_exc); Py_XINCREF(old_exc);
...@@ -440,6 +445,10 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, ...@@ -440,6 +445,10 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
PyErr_WriteUnraisable(ctx); PyErr_WriteUnraisable(ctx);
Py_DECREF(ctx); Py_DECREF(ctx);
} }
#ifdef WITH_THREAD
if (nogil)
PyGILState_Release(state);
#endif
} }
/////////////// AddTraceback.proto /////////////// /////////////// AddTraceback.proto ///////////////
......
# mode: run
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
def test(int x): def test(int x):
""" """
>>> test(5) >>> test(5)
...@@ -35,3 +43,23 @@ def test_nogil_exception_propagation(): ...@@ -35,3 +43,23 @@ def test_nogil_exception_propagation():
""" """
with nogil: with nogil:
nogil_func() 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