➜

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 Kevin Shweh
Recipients Kevin Shweh
Date 2022-02-11.23:47:13
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <[email protected]>
In-reply-to
Content
This code in Thread._wait_for_tstate_lock:

    try:
        if lock.acquire(block, timeout):
            lock.release()
            self._stop()
    except:
        if lock.locked():
            # bpo-45274: lock.acquire() acquired the lock, but the function
            # was interrupted with an exception before reaching the
            # lock.release(). It can happen if a signal handler raises an
            # exception, like CTRL+C which raises KeyboardInterrupt.
            lock.release()
            self._stop()
        raise

has a bug. The "if lock.locked()" check doesn't check whether this code managed to acquire the lock. It checks if *anyone at all* is holding the lock. The lock is almost always locked, so this code will perform a spurious call to self._stop() if it gets interrupted while trying to acquire the lock.

Thread.join uses this method to wait for a thread to finish, so a thread will spuriously be marked dead if you interrupt a join call with Ctrl-C while it's trying to acquire the lock. Here's a reproducer:


import time
import threading
 
event = threading.Event()
 
def target():
    event.wait()
    print('thread done')
 
t = threading.Thread(target=target)
t.start()
print('joining now')
try:
    t.join()
except KeyboardInterrupt:
    pass
print(t.is_alive())
event.set()


Interrupt this code with Ctrl-C during the join(), and print(t.is_alive()) will print False.
History
Date User Action Args
2022-02-11 23:47:13Kevin Shwehsetrecipients: + Kevin Shweh
2022-02-11 23:47:13Kevin Shwehsetmessageid: <[email protected]>
2022-02-11 23:47:13Kevin Shwehlinkissue46726 messages
2022-02-11 23:47:13Kevin Shwehcreate