Exception being ignored in __dealloc__ (and in C++ class destructor)
See original GitHub issueHi, I have a code that is like the following simplified test case:
cdef class RaiseOnDealloc:
def __cinit__(self):
print('Entered RaiseOnDealloc.__cinit__')
def __dealloc__(self):
print('Entered RaiseOnDealloc.__dealloc__')
raise RuntimeError('Something bad')
print('After raising')
def test_raise_on_dealloc():
print('Entered test_raise_on_dealloc')
cdef RaiseOnDealloc r = RaiseOnDealloc()
print('Body of test_raise_on_dealloc')
the output of calling test_raise_on_dealloc()
is this:
Entered test_raise_on_dealloc
Entered RaiseOnDealloc.__cinit__
Body of test_raise_on_dealloc
Entered RaiseOnDealloc.__dealloc__
Exception ignored in: 'RaiseOnDealloc.__dealloc__'
RuntimeError: Something bad
The RuntimeError
is not being propagated by test_raise_on_dealloc
. Is there a way for it to not be ignored? Unfortunately __dealloc__
is only valid as a def
function, and it doesn’t accept except +
.
Even if I move the class to C++ and declare it with cdef cppclass
, it’s still not possible to propagate exceptions from its destructor, since there seems to be no way to declare destructors on cdef cppclass
declarations.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:3
- Comments:10 (1 by maintainers)
Top Results From Across the Web
Are destructors called after a throw in C++? - Stack Overflow
Yes, destructors are guaranteed to be called on stack unwinding, including unwinding due to exception being thrown. There are ...
Read more >Exception Handling in C++ - Saylor Academy
The class Botch not only throws an exception inside f( ), but also in its destructor. This causes a call to terminate( ),...
Read more >1: Exception handling
The problem with C++ is that longjmp( ) doesn't respect objects; in particular it doesn't call destructors when it jumps out of a...
Read more >Finalize Instead Of Proper Destructor - C2 wiki
A better replacement is "with" in C#, but to make it safe, "with" should also ... Useful: pass 'abort/retry/ignore' continuations as part of...
Read more >Exception specification in derived class - C++ Forum
It sounds like it is not aware of C++11. Nowadays it is assumed that the destructor never throws even if there is no...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Is there really anything to work around? Ultimately your options are:
__dealloc__
in a try-catch block)All of the first three options seem equally unsatisfactory to me. But ultimately it is only an warning message - it doesn’t break your program.
As a general rule you shouldn’t be raising exceptions from destructors (either from C++ or Python). The basic problem is that destructors are often called while handling other exceptions and you can’t have two exceptions at once.
It isn’t completely clear from the documentation what the rules are for exceptions in
tp_dealloc
.tp_finalize
(which we don’t yet support) definitely requires the exception state to be restored on exit.So I’m not really convinced this is a bug. Swallowing the exception is definitely a sensible implementation choice (and probably the most sensible one)
https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation:
That, to me, suggests you pretty much have to clear the exception state in the destructor.