You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable #89464
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2021-09-27.14:26:03.506>labels= ['library', '3.11']
title='pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable'updated_at=<Date2021-09-28.06:30:07.878>user='https://github.com/vstinner'
I recently worked on time.sleep() enhancement (bpo-21302) and threading bugfixes (bpo-45274, bpo-1596321). I saw one more time that Python emulates conditional variables to support Windows XP and older. But Python 3.11 requires Windows 8.1 or newer. IMO it's time to remove _PY_EMULATED_WIN_CV code path from pycore_condvar.h.
IMO it's time to remove _PY_EMULATED_WIN_CV code path from
pycore_condvar.h.
SleepConditionVariableSRW() can't be interrupted in PyCOND_WAIT() and PyCOND_TIMEDWAIT(). Maybe a hybrid solution could be adopted. Use native condition variables for the GIL, where performance matters and the ability to interrupt the wait doesn't matter. Otherwise use the semaphore implementation, for which the wait implementation can be modified to use WaitForMultipleObjects(), and include the Ctrl+C event.
SleepConditionVariableSRW() can't be interrupted in PyCOND_WAIT() and PyCOND_TIMEDWAIT().
Oh. A comment on StackOverlow says:
"The WaitForXxx functions accept parameters of the generic HANDLE type, which represents a handle to a kernel object. Condition variables are user-mode objects, not kernel objects, so you cannot use them with these functions, since they work only with kernel objects."
I only created this issue because of this comment in pycore_condvar.h:
---
/* non-emulated condition variables are provided for those that want * to target Windows Vista. Modify this macro to enable them. */#ifndef_PY_EMULATED_WIN_CV#define_PY_EMULATED_WIN_CV 1 /* use emulated condition variables */#endif
changed the title [-]pycore_condvar.h: remove Windows conditonal variable emulation[/-][+]pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable[/+]on Sep 27, 2021
changed the title [-]pycore_condvar.h: remove Windows conditonal variable emulation[/-][+]pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable[/+]on Sep 27, 2021
FYI, waiting for a condition variable can cause a thread to enter a wait state that's interruptible, in theory, but the mechanism is different since condition variables and SRW locks are pointer-sized values in user space, instead of NT objects in kernel space. The current implementation is based on the system call NtWaitForAlertByThreadId(address, timeout), which enters the "WrAlertByThreadId" wait state. The address parameter is that of the SRW lock. The kernel sets this as the 'object' for the wait, but the wait is actually satisfied by alerting the thread directly via NtAlertThreadByThreadId(tid). ISTM, they could have added a function that calls the latter to cancel a wait on a given thread. That would have been useful for Ctrl+C since the handler executes on a new thread.
Activity
vstinner commentedon Sep 27, 2021
I recently worked on time.sleep() enhancement (bpo-21302) and threading bugfixes (bpo-45274, bpo-1596321). I saw one more time that Python emulates conditional variables to support Windows XP and older. But Python 3.11 requires Windows 8.1 or newer. IMO it's time to remove _PY_EMULATED_WIN_CV code path from pycore_condvar.h.
vstinner commentedon Sep 27, 2021
See also bpo-29971 "Lock.acquire() not interruptible on Windows".
eryksun commentedon Sep 27, 2021
SleepConditionVariableSRW() can't be interrupted in PyCOND_WAIT() and PyCOND_TIMEDWAIT(). Maybe a hybrid solution could be adopted. Use native condition variables for the GIL, where performance matters and the ability to interrupt the wait doesn't matter. Otherwise use the semaphore implementation, for which the wait implementation can be modified to use WaitForMultipleObjects(), and include the Ctrl+C event.
zooba commentedon Sep 27, 2021
This was my immediate reaction as well.
Unfortunately, we keep seeing that all waits need to be interruptible, so either a WaitForMultipleObjects or a slow spinlock.
vstinner commentedon Sep 27, 2021
Eryk:
Oh. A comment on StackOverlow says:
"The WaitForXxx functions accept parameters of the generic HANDLE type, which represents a handle to a kernel object. Condition variables are user-mode objects, not kernel objects, so you cannot use them with these functions, since they work only with kernel objects."
https://stackoverflow.com/questions/37522108/can-you-really-wait-on-condition-variable-with-waitfor-objects
I only created this issue because of this comment in pycore_condvar.h:
---
[-]pycore_condvar.h: remove Windows conditonal variable emulation[/-][+]pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable[/+][-]pycore_condvar.h: remove Windows conditonal variable emulation[/-][+]pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable[/+]eryksun commentedon Sep 28, 2021
FYI, waiting for a condition variable can cause a thread to enter a wait state that's interruptible, in theory, but the mechanism is different since condition variables and SRW locks are pointer-sized values in user space, instead of NT objects in kernel space. The current implementation is based on the system call NtWaitForAlertByThreadId(address, timeout), which enters the "WrAlertByThreadId" wait state. The address parameter is that of the SRW lock. The kernel sets this as the 'object' for the wait, but the wait is actually satisfied by alerting the thread directly via NtAlertThreadByThreadId(tid). ISTM, they could have added a function that calls the latter to cancel a wait on a given thread. That would have been useful for Ctrl+C since the handler executes on a new thread.
vstinner commentedon Nov 3, 2022
Sadly, I don't have the bandwidth to work on this issue, I just close it.
First, I understood that it was just deadcode. Nope. It's way more complicated than what I expected!