◐ Shell
clean mode source ↗

bpo-41710: PyThread_acquire_lock_timed() uses sem_clockwait() by vstinner · Pull Request #28662 · python/cpython

Conversation

@vstinner

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.

https://bugs.python.org/issue41710

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.

vstinner

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.

vstinner

#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.

@vstinner

@vstinner

gpshead

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!

corona10

@vstinner