You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
When raising a Python exception in a cdef function marked with except +, the exception is not always propagated to the call site. Related to #2603, most likely due to #2615 (comment). Can it be made safe by replacing except + with except *?
To Reproduce
Three files are needed to reproduce the behaviour.
defto_bytes(s):
ifisinstance(s, unicode):
return ( <unicode> s).encode("utf8")
return s
In helloworld.pyx:
import helloworld_utils
from libcpp.string cimport string
from libcpp.unordered_map cimport unordered_map
ctypedef unordered_map[string, string] VarMap
cdef class MyClass:
def__init__(self, value):
cdef VarMap converted_value
converted_value[helloworld_utils.to_bytes("value")] = python_object_to_variant(value)
cdef string python_object_to_variant(value) except+:
cdef string out
# if isinstance(value, str):# out = helloworld_utils.to_bytes(value)# return outraiseTypeError(f"cannot convert type {type(value)} to std::string")
Running make to build the module and run the python script results in message "No error was raised!" being printed to stdout.
Expected behavior
The expected outcome is a TypeError, and it can be obtained by doing one of the following actions:
uncommenting the commented lines in the body of python_object_to_variant()
replacing helloworld_utils.to_bytes("value") with b"value" in MyClass.__init__()
replacing helloworld_utils.to_bytes("value") with to_bytes("value") in MyClass.__init__() and copy-pasting the definition of to_bytes() in helloworld.pyx
adding except + to U& operator[](T&) in Cython/Includes/libcpp/unordered_map.pxd
replacing converted_value[a] = b by converted_value.insert(pair[string, string](a, b))
Environment:
Reproducible in 2 environments:
OS: Ubuntu 20.04 resp. Ubuntu 22.04
Python version 3.8.10 resp. 3.9.5
Cython version 0.29.14 resp. 0.29.21
Additional context
The bug is always reproducible in the minimal working example provided above, however the bug originally surfaced in a larger Cython project where it happened at random and infrequently. According to Exception handling in cython cdef declarations, declaring the cdef function with except * seems to be the preferred approach in this situation, although it comes with a small overhead. According to #2603, declaring the cdef function with except + shouldn't prevent the propagation of Python exceptions.
The text was updated successfully, but these errors were encountered:
It isn't completely obvious from the issues you link, but except+ only makes sense for extern functions. Cython functions never raise c++ exceptions and they should never allow c++ exceptions to propagate through them (they only handle reference counting correctly if the c++ exception is caught and handled/converted immediately).
There may be a genuine issue here, but in this case the function should just be except *
Fix a regression introduced in #4387 that would randomly block the propagation of a `TypeError` when converting an unsupported Python type to a C++ variant. Please refer to cython/cython#4720 for the details. Restore the corresponding `TypeError` checks in the testsuite.
Describe the bug
When raising a Python exception in a cdef function marked with
except +
, the exception is not always propagated to the call site. Related to #2603, most likely due to #2615 (comment). Can it be made safe by replacingexcept +
withexcept *
?To Reproduce
Three files are needed to reproduce the behaviour.
In
Makefile
:In
helloworld_utils.pyx
:In
helloworld.pyx
:Running
make
to build the module and run the python script results in message"No error was raised!"
being printed to stdout.Expected behavior
The expected outcome is a
TypeError
, and it can be obtained by doing one of the following actions:python_object_to_variant()
helloworld_utils.to_bytes("value")
withb"value"
inMyClass.__init__()
helloworld_utils.to_bytes("value")
withto_bytes("value")
inMyClass.__init__()
and copy-pasting the definition ofto_bytes()
inhelloworld.pyx
except +
withexcept *
The following workarounds didn't help:
except +
withexcept +*
(due to Bad code generated forexcept +*
function #3065)except +
toU& operator[](T&)
inCython/Includes/libcpp/unordered_map.pxd
converted_value[a] = b
byconverted_value.insert(pair[string, string](a, b))
Environment:
Reproducible in 2 environments:
Additional context
The bug is always reproducible in the minimal working example provided above, however the bug originally surfaced in a larger Cython project where it happened at random and infrequently. According to Exception handling in cython cdef declarations, declaring the cdef function with
except *
seems to be the preferred approach in this situation, although it comes with a small overhead. According to #2603, declaring the cdef function withexcept +
shouldn't prevent the propagation of Python exceptions.The text was updated successfully, but these errors were encountered: