From: Antoine Pitrou Date: Mon, 26 Jun 2017 20:13:39 +0000 (+0200) Subject: [2.7] bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to (GH... X-Git-Tag: v2.7.14rc1~79 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=828488393ca79f2ceb0acc2d7c30fb68baad85f8;p=python [2.7] bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to (GH-2403) (#2420) * [2.7] bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to (GH-2403) * bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to lock This is especially important if PyThread_acquire_lock() is called reentrantly (for example from a signal handler). * Update 2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst * Avoid core logic when taking the mutex failed. (cherry picked from commit f84ac420c2af98339678744953869cad3c253281) * Remove test undef --- diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst b/Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst new file mode 100644 index 0000000000..08d76cb965 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst @@ -0,0 +1,2 @@ +Avoid blocking in pthread_mutex_lock() when PyThread_acquire_lock() is asked +not to block. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index c9ed796cd0..79c66d4f32 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -410,31 +410,41 @@ PyThread_free_lock(PyThread_type_lock lock) int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success; + int success = 0; pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - status = pthread_mutex_lock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_lock[1]"); - success = thelock->locked == 0; - - if ( !success && waitflag ) { - /* continue trying until we get the lock */ - - /* mut must be locked by me -- part of the condition - * protocol */ - while ( thelock->locked ) { - status = pthread_cond_wait(&thelock->lock_released, - &thelock->mut); - CHECK_STATUS("pthread_cond_wait"); + if (waitflag) { + status = pthread_mutex_lock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_lock[1]"); + } + else { + status = pthread_mutex_trylock( &thelock->mut ); + if (status != EBUSY) + CHECK_STATUS("pthread_mutex_trylock[1]"); + } + if (status == 0) { + success = thelock->locked == 0; + + if ( !success && waitflag ) { + /* continue trying until we get the lock */ + + /* mut must be locked by me -- part of the condition + * protocol */ + while ( thelock->locked ) { + status = pthread_cond_wait(&thelock->lock_released, + &thelock->mut); + CHECK_STATUS("pthread_cond_wait"); + } + success = 1; } - success = 1; + + if (success) thelock->locked = 1; + status = pthread_mutex_unlock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_unlock[1]"); } - if (success) thelock->locked = 1; - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_unlock[1]"); if (error) success = 0; dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));