]> granicus.if.org Git - python/commitdiff
[2.7] bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to (GH...
authorAntoine Pitrou <pitrou@free.fr>
Mon, 26 Jun 2017 20:13:39 +0000 (22:13 +0200)
committerGitHub <noreply@github.com>
Mon, 26 Jun 2017 20:13:39 +0000 (22:13 +0200)
* [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

Misc/NEWS.d/next/Core and Builtins/2017-06-26-14-29-50.bpo-30765.Q5iBmf.rst [new file with mode: 0644]
Python/thread_pthread.h

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 (file)
index 0000000..08d76cb
--- /dev/null
@@ -0,0 +1,2 @@
+Avoid blocking in pthread_mutex_lock() when PyThread_acquire_lock() is asked
+not to block.
index c9ed796cd0fe0afe26af863f249495140ea77a2b..79c66d4f32c51f7071f81b63132890edff205dc4 100644 (file)
@@ -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));