@@ -842,10 +842,15 @@ def generate_dealloc_for_class(
842842 emitter .emit_line ("static void" )
843843 emitter .emit_line (f"{ dealloc_func_name } ({ cl .struct_name (emitter .names )} *self)" )
844844 emitter .emit_line ("{" )
845+ emitter .emit_line ("int finalize_error = 0;" )
846+ emitter .emit_line ("PyObject *type, *value, *traceback;" )
847+ emitter .emit_line ("PyErr_Fetch(&type, &value, &traceback);" )
845848 if has_tp_finalize :
846849 emitter .emit_line ("if (!PyObject_GC_IsFinalized((PyObject *)self)) {" )
847- emitter .emit_line ("Py_TYPE(self)->tp_finalize ((PyObject *)self);" )
850+ emitter .emit_line ("PyObject_CallFinalizerFromDealloc ((PyObject *)self);" )
848851 emitter .emit_line ("}" )
852+ emitter .emit_line ("if (PyErr_Occurred() != NULL) finalize_error = 1;" )
853+ emitter .emit_line ("PyErr_Restore(type, value, traceback);" )
849854 emitter .emit_line ("PyObject_GC_UnTrack(self);" )
850855 if cl .reuse_freed_instance :
851856 emit_reuse_dealloc (cl , emitter )
@@ -854,6 +859,13 @@ def generate_dealloc_for_class(
854859 emitter .emit_line (f"{ clear_func_name } (self);" )
855860 emitter .emit_line ("Py_TYPE(self)->tp_free((PyObject *)self);" )
856861 emitter .emit_line ("CPy_TRASHCAN_END(self)" )
862+ # # CPython interpreter uses PyErr_WriteUnraisable: https://docs.python.org/3/c-api/exceptions.html#c.PyErr_WriteUnraisable
863+ # # However, the message is slightly different due to the way mypyc compiles classes.
864+ # # CPython interpreter prints: Exception ignored in: <function F.__del__ at 0x100aed940>
865+ # # mypyc prints: Exception ignored in: <slot wrapper '__del__' of 'F' objects>
866+ emitter .emit_line ("if (finalize_error == 1) {" )
867+ emitter .emit_line ("PyErr_WriteUnraisable((PyObject *)self);" )
868+ emitter .emit_line ("}" )
857869 emitter .emit_line ("}" )
858870
859871
@@ -884,30 +896,13 @@ def generate_finalize_for_class(
884896 emitter .emit_line ("static void" )
885897 emitter .emit_line (f"{ finalize_func_name } (PyObject *self)" )
886898 emitter .emit_line ("{" )
887- emitter .emit_line ("PyObject *type, *value, *traceback;" )
888- emitter .emit_line ("PyErr_Fetch(&type, &value, &traceback);" )
889899 emitter .emit_line (
890900 "{}{}{}(self);" .format (
891901 emitter .get_group_prefix (del_method .decl ),
892902 NATIVE_PREFIX ,
893903 del_method .cname (emitter .names ),
894904 )
895905 )
896- emitter .emit_line ("if (PyErr_Occurred() != NULL) {" )
897- emitter .emit_line ('PyObject *del_str = PyUnicode_FromString("__del__");' )
898- emitter .emit_line (
899- "PyObject *del_method = (del_str == NULL) ? NULL : _PyType_Lookup(Py_TYPE(self), del_str);"
900- )
901- # CPython interpreter uses PyErr_WriteUnraisable: https://docs.python.org/3/c-api/exceptions.html#c.PyErr_WriteUnraisable
902- # However, the message is slightly different due to the way mypyc compiles classes.
903- # CPython interpreter prints: Exception ignored in: <function F.__del__ at 0x100aed940>
904- # mypyc prints: Exception ignored in: <slot wrapper '__del__' of 'F' objects>
905- emitter .emit_line ("PyErr_WriteUnraisable(del_method);" )
906- emitter .emit_line ("Py_XDECREF(del_method);" )
907- emitter .emit_line ("Py_XDECREF(del_str);" )
908- emitter .emit_line ("}" )
909- # PyErr_Restore also clears exception raised in __del__.
910- emitter .emit_line ("PyErr_Restore(type, value, traceback);" )
911906 emitter .emit_line ("}" )
912907
913908
0 commit comments