From afaaf4b2c57c997430c71ad815bf979d2639969f Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 26 Jun 2017 20:41:07 +0200 Subject: [PATCH 1/2] [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) --- .../2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst | 2 + Python/thread_pthread.h | 47 ++++++++++++------- 2 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst 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 000000000000000..08d76cb965e3691 --- /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 c9ed796cd0fe0af..8f96eca284f391d 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -81,6 +81,7 @@ #else # undef USE_SEMAPHORES #endif +# undef USE_SEMAPHORES /* On platforms that don't use standard POSIX threads pthread_sigmask() @@ -410,31 +411,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)); From 689446ace0b5c88a5ed7c449b89b50aa336091c5 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 26 Jun 2017 21:07:05 +0200 Subject: [PATCH 2/2] Remove test undef --- Python/thread_pthread.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 8f96eca284f391d..79c66d4f32c51f7 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -81,7 +81,6 @@ #else # undef USE_SEMAPHORES #endif -# undef USE_SEMAPHORES /* On platforms that don't use standard POSIX threads pthread_sigmask()