bpo-41710: PyThread_acquire_lock_timed() uses sem_clockwait() by vstinner · Pull Request #28662 · python/cpython
Conversation
On Unix, if the sem_clockwait() function is available in the C
library (glibc 2.30 and newer), the threading.Lock.acquire() method
now uses the monotonic clock (time.CLOCK_MONOTONIC) for the timeout,
rather than using the system clock (time.CLOCK_REALTIME), to not be
affected by system clock changes.
configure now checks if the sem_clockwait() function is available.
On Unix, if the sem_clockwait() function is available in the C library (glibc 2.30 and newer), the threading.Lock.acquire() method now uses the monotonic clock (time.CLOCK_MONOTONIC) for the timeout, rather than using the system clock (time.CLOCK_REALTIME), to not be affected by system clock changes. configure now checks if the sem_clockwait() function is available.
| if (timeout > 0) { | ||
| #ifdef HAVE_SEM_CLOCKWAIT | ||
| struct timespec abs_timeout; | ||
| _PyTime_AsTimespec_clamp(deadline, &abs_timeout); |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if sem_clockwait() timeout argument can be modified by the function, for example if the wait is interrupted by a signal. In case of doubt, I prefer to compute abs_timeout before each call.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the same file, pthread_cond_timedwait() absolute timeout is only computed once outside the loop. I understand that we can also compute abs_timeout once outside the loop.
The new implementation of time.sleep(), pysleep() function, now also uses an absolute timeout (timespec) computed once outside the loop. It uses clock_nanosleep() or nanosleep(). These functions have an argument for the remaining time, it's not used by pysleep().
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #ifdef HAVE_SEM_CLOCKWAIT | ||
| struct timespec abs_timeout; | ||
| _PyTime_AsTimespec_clamp(deadline, &abs_timeout); | ||
| status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC, &abs_timeout)); |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if sem_clockwait() can fail with ENOSYS if Python is built with a recent glibc and then run with an older glibc or a different kernel version.
Should we attempt to fallback to sem_timedwait() if sem_clockwait() "doesn't work"? How can we determine if sem_clockwait() "doesn't work"? So far, I failed to find a sem_clockwait() documentation or manual page.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of doubt, I prefer to leave the code as it is, and only implement a fallback once we can test it on a real system.
| break; | ||
| } | ||
|
|
||
| // sem_clockwait() uses an absolution timeout, there is no need |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/absolution/absolute
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nobody expects the Spanish Absolution!