Skip to content

ThreadPoolExecutorTest.test_no_stale_references may hang with GIL disabled #117688

Closed
@colesbury

Description

@colesbury

In #114824, I modified test_no_stale_references so that it passes in the --disable-gil build. Unfortunately, that change was not sufficient and the test may still hang once the GIL is actually disabled.

Relevant code:

my_object = MyObject()
my_object_collected = threading.Event()
my_object_callback = weakref.ref(
my_object, lambda obj: my_object_collected.set())

collected = my_object_collected.wait(timeout=support.SHORT_TIMEOUT)

The problem is due to the combination of two issues:

  • Due to biased reference counting, the destructor for my_object is usually called on the main thread asynchronously (by the eval breaker logic)
  • The destructor may be called somewhere in the implementation of my_object_collected.wait(). The my_object_collected.wait() implementation holds some of the same locks that my_object_collected.set() also needs. This can lead to deadlock if the timing is unlucky: the my_object_collected.set() call from the weakref callback tries to acquire locks already held by the current thread and deadlocks.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions