diff options
author | Antoine Pitrou <pitrou@free.fr> | 2017-06-26 20:13:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-26 20:13:39 (GMT) |
commit | 828488393ca79f2ceb0acc2d7c30fb68baad85f8 (patch) | |
tree | a39a997f59b8482e4f2c35e4749b287a5a00f9e5 | |
parent | 787826c9316b03ac8a197078ec1cdf98fa840c5c (diff) | |
download | cpython-828488393ca79f2ceb0acc2d7c30fb68baad85f8.zip cpython-828488393ca79f2ceb0acc2d7c30fb68baad85f8.tar.gz cpython-828488393ca79f2ceb0acc2d7c30fb68baad85f8.tar.bz2 |
[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
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst | 2 | ||||
-rw-r--r-- | Python/thread_pthread.h | 46 |
2 files changed, 30 insertions, 18 deletions
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 0000000..08d76cb --- /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 c9ed796..79c66d4 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)); |