This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients Mark.Shannon, christian.heimes, jdemeyer, lukasz.langa, pablogsal, petr.viktorin, pitrou, vstinner
Date 2019-09-03.12:45:01
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
Second step: when func_clear() is called, the closure is cleared. Clearing the closure should call the function which is being cleared (or is already cleared).

import gc

class CallFunc:
    def __del__(self):
        func = self.func
        if func is None:
        print("CallFunc", func)
        func("call func from CallFunc.__del__")

def create_remove():
    call_func = CallFunc()
    def remove(msg):
        x = call_func
    remove.__name__ = "evil_func"
    call_func.func = remove
    return call_func, remove

call_func, remove = create_remove()
print("== clear ==")
call_func = None
remove = None

print("== collect ==")

print("== exit ==")

Output (with my hacked CPython):
== clear ==

== collect ==
CallFunc <function create_remove.<locals>.remove at 0x7fab8a189eb0>
call func from CallFunc.__del__
func_clear remove() -- in delete_garbage? 1

== exit ==

call_func and remove are part of a reference cycle. A forced garbage collection breaks the cycle and removes the two objects, but they are not removed in the expected order:

* first: call_func
* then: remove

The crash requires to destroy the objects in the reverse order
Date User Action Args
2019-09-03 12:45:01vstinnersetrecipients: + vstinner, pitrou, christian.heimes, petr.viktorin, lukasz.langa, Mark.Shannon, jdemeyer, pablogsal
2019-09-03 12:45:01vstinnersetmessageid: <>
2019-09-03 12:45:01vstinnerlinkissue38006 messages
2019-09-03 12:45:01vstinnercreate