Skip to content

Possible lost notification in threading.Condition when a waiter times out #160414

Open

Description

@0x-bala

Bug report

Hi,

I noticed some unexpected behavior while testing threading.Condition on Python 3.14.4.

I created two threads waiting on the same condition. The first thread has a short timeout, while the second has a longer timeout. I then held the condition lock until the first waiter's timeout expired and called notify(1).

In my test, both wait() calls returned False, even though I called notify(1) while two waiters were still present in the internal wait queue. I observed the same result in 100 consecutive runs.

I'm not sure whether this is expected behavior or a race condition in how timed-out waiters are handled. Could someone clarify whether this behavior is expected? If not, it may be possible for a notification to be consumed by a waiter whose timeout has already expired, leaving another waiter waiting until its own timeout.

I can provide the minimal reproduction script and terminal output to help investigate.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. 0x-bala commented on Oct 23, 2026

    @0x-bala
    Author

    import sys
    import threading
    import time

    def poc_condition_notify_lost():
    cond = threading.Condition()
    res = {}

    t1_in = threading.Event()
    t2_in = threading.Event()
    
    def w1():
        with cond:
            t1_in.set()
            res["t1"] = cond.wait(timeout=0.02)
    
    def w2():
        t1_in.wait()
        with cond:
            t2_in.set()
            res["t2"] = cond.wait(timeout=0.2)
    
    a = threading.Thread(target=w1)
    b = threading.Thread(target=w2)
    
    a.start()
    b.start()
    t2_in.wait()
    
    with cond:
        time.sleep(0.05)
        cond.notify(1)
    
    a.join()
    b.join()
    
    print("Python:", sys.version)
    print("Results:", res)
    
    if res == {"t1": False, "t2": False}:
        print("Observed: both wait calls returned False")
    else:
        print("Observed:", res)
    

    if name == "main":
    poc_condition_notify_lost()

  2. NekoAsakura commented on Oct 23, 2026

    @NekoAsakura
    Member

    Thanks for the bug report!

  3. added a commit that references this issue on Oct 23, 2026
  4. NekoAsakura commented on Oct 24, 2026

    @NekoAsakura
    Member

    Reopening for the pending fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions