[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-13 Thread Eryk Sun
Eryk Sun added the comment: > I didn't have that in mind at all. I understood what you had in mind, and I don't disagree. I was just highlighting that the only somewhat important work done in _stop() is to clean up the _shutdown_locks set, to keep it from growing too large. But that task is

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-13 Thread Tim Peters
Tim Peters added the comment: > It's nice that _maintain_shutdown_locks() gets > called in _stop(), but the more important call site is in > _set_tstate_lock(). I didn't have that in mind at all. What at the Python level cares whether the thread is alive? Well. is_alive() does, and it calls

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-13 Thread Eryk Sun
Eryk Sun added the comment: > Anything at the Python level that cares whether the thread is > still alive will call _wait_for_tstate_lock() again It's nice that _maintain_shutdown_locks() gets called in _stop(), but the more important call site is in _set_tstate_lock(). I typed up the

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-13 Thread Tim Peters
Tim Peters added the comment: >> is there a bulletproof way to guarantee that `self._stop()` gets >> called if the acquire_and_release() succeeds? > I don't think it's critical. Agreed! Anything at the Python level that cares whether the thread is still alive will call

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-13 Thread Eryk Sun
Eryk Sun added the comment: > is there a bulletproof way to guarantee that `self._stop()` gets > called if the acquire_and_release() succeeds? I don't think it's critical. But we still should deal with the common case in Windows in which a KeyboardInterrupt is raised immediately after the

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Tim Peters
Tim Peters added the comment: While bundling the lock.release() into C makes that bulletproof, is there a bulletproof way to guarantee that `self._stop()` gets called if the acquire_and_release() succeeds? Offhand, I don't see a reason for why that isn't just as vulnerable to getting

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Tim Peters
Tim Peters added the comment: > Maybe add an `acquire_and_release()` method Bingo - that should do the trick, in an "obviously correct" way. Of course it's of limited applicability, but fine by me. Will you open a PR with this code? -- ___

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Eryk Sun
Eryk Sun added the comment: > Wrap everything needed in a custom C function. Maybe add an `acquire_and_release()` method: static PyObject * lock_PyThread_acquire_and_release_lock( lockobject *self, PyObject *args, PyObject *kwds) { _PyTime_t timeout;

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Tim Peters
Tim Peters added the comment: Na, we've been doing excruciatingly clever stuff to deal with thread shutdown for decades, and it always proves to be wrong in some way. Even if code like except: if lock.locked(): lock.release() self._stop() raise did work as hoped for,

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Eryk Sun
Eryk Sun added the comment: > If the acquire() in fact times out, but the store to the `acquired` > variable is interrupted, `if _WINDOWS and acquired is None` will > succeed, despite that the lock is still locked Yeah, my proposed workaround is no good, so we can't resolve this without a

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Tim Peters
Tim Peters added the comment: Eryk, I don't think that workaround is solid on Windows in all cases. For example, if .join() is called with a timeout, the same timeout is passed to lock.acquire(block, timeout). If the acquire() in fact times out, but the store to the `acquired` variable is

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Eryk Sun
Eryk Sun added the comment: > The race on := is much smaller than the original race > and I suspect in practice will be very hard to hit. In Windows, the acquire() method of a lock can't be interrupted. Thus, in the main thread, an exception from Ctrl+C gets raised as soon as acquire()

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-12 Thread Serhiy Storchaka
Change by Serhiy Storchaka : -- nosy: +pitrou ___ Python tracker ___ ___ Python-bugs-list mailing list Unsubscribe:

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Ben
Change by Ben : -- nosy: +serhiy.storchaka ___ Python tracker ___ ___ Python-bugs-list mailing list Unsubscribe:

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Ben
Ben added the comment: You are right, What one really needs here is a way to know *who* owns the lock, but threading.Lock does not provide that. The race on := is much smaller than the original race and I suspect in practice will be very hard to hit. As the original bpo notes, it may not

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh
Kevin Shweh added the comment: The PR you submitted doesn't work, unfortunately. It essentially reintroduces issue 45274. If this line: if locked := lock.acquire(block, timeout): gets interrupted between the acquire and the assignment, locked is still False. That's rare, but so is an

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh
Kevin Shweh added the comment: Issue 45274 was a subtly different issue. That was a problem that happened if the thread got interrupted *between* the acquire and the release, causing it to *not* release the lock and *not* perform end-of-thread cleanup. The fix for that issue caused this

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread James Gerity
Change by James Gerity : -- nosy: +SnoopJeDi ___ Python tracker ___ ___ Python-bugs-list mailing list Unsubscribe:

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Ben
Change by Ben : -- nosy: +vstinner ___ Python tracker ___ ___ Python-bugs-list mailing list Unsubscribe:

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Ben
Ben added the comment: This is a duplicate of https://bugs.python.org/issue45274 but the patch there did not fix it I've just added a PR there (or should it go here?) that (i think) fixes this. The issue is that the lock.locked() call just checks that *someone* has the lock, not that the

[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh
New submission from Kevin Shweh : 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