◐ Shell
clean mode source ↗

Message 302257 - Python tracker

threading.Timer is implemented with threading.Event.wait(timeout) which is implemented with threading.Condition.wait(timeout).

threading.Condition.wait(timeout) creates a lock called "waiter" and uses it to implement the wait:

   waiter.acquire(True, timeout)

So at the end of the chain, you find a lock created by _thread.allocate_lock() and the Lock.acquire(True, timeout) call.

At the C level, a lock is created by PyThread_allocate_lock(). The implementation of PyThread_allocate_lock() depends on the platform. Check:

>>> sys.thread_info
sys.thread_info(name='pthread', lock='semaphore', version='NPTL 2.25')

So in my case (Fedora 25), a Python lock is implemented as a semaphore:

* create the lock: sem_init()
* acquire the lock with a timeout: sem_timedwait(thelock, &ts)

The problem is that the sem_timedwait() function of the glibc doesn't allow to specify which clock is used:

https://sourceware.org/bugzilla/show_bug.cgi?id=14717

The second problem is that the glibc relies on the Linux kernel, and the kernel doesn't support specifiying a clock (extract of the glib bug):

"It seems this would need kernel work"

--

For sys.thread_info.lock == "mutex+cond", PyThread_allocate_lock(timeout) is implemented with pthread_mutex_lock() + pthread_cond_timedwait(). The good news is that this API allows to specify the clock:

pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &attr);

... I already created bpo-23428 to call "pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);" in Python, it was 2 years ago ;-)