Skip to content

Commit 8284883

Browse files
authored
[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 f84ac42) * Remove test undef
1 parent 787826c commit 8284883

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid blocking in pthread_mutex_lock() when PyThread_acquire_lock() is asked
2+
not to block.

‎Python/thread_pthread.h‎

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -410,31 +410,41 @@ PyThread_free_lock(PyThread_type_lock lock)
410410
int
411411
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
412412
{
413-
int success;
413+
int success = 0;
414414
pthread_lock *thelock = (pthread_lock *)lock;
415415
int status, error = 0;
416416

417417
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
418418

419-
status = pthread_mutex_lock( &thelock->mut );
420-
CHECK_STATUS("pthread_mutex_lock[1]");
421-
success = thelock->locked == 0;
422-
423-
if ( !success && waitflag ) {
424-
/* continue trying until we get the lock */
425-
426-
/* mut must be locked by me -- part of the condition
427-
* protocol */
428-
while ( thelock->locked ) {
429-
status = pthread_cond_wait(&thelock->lock_released,
430-
&thelock->mut);
431-
CHECK_STATUS("pthread_cond_wait");
419+
if (waitflag) {
420+
status = pthread_mutex_lock( &thelock->mut );
421+
CHECK_STATUS("pthread_mutex_lock[1]");
422+
}
423+
else {
424+
status = pthread_mutex_trylock( &thelock->mut );
425+
if (status != EBUSY)
426+
CHECK_STATUS("pthread_mutex_trylock[1]");
427+
}
428+
if (status == 0) {
429+
success = thelock->locked == 0;
430+
431+
if ( !success && waitflag ) {
432+
/* continue trying until we get the lock */
433+
434+
/* mut must be locked by me -- part of the condition
435+
* protocol */
436+
while ( thelock->locked ) {
437+
status = pthread_cond_wait(&thelock->lock_released,
438+
&thelock->mut);
439+
CHECK_STATUS("pthread_cond_wait");
440+
}
441+
success = 1;
432442
}
433-
success = 1;
443+
444+
if (success) thelock->locked = 1;
445+
status = pthread_mutex_unlock( &thelock->mut );
446+
CHECK_STATUS("pthread_mutex_unlock[1]");
434447
}
435-
if (success) thelock->locked = 1;
436-
status = pthread_mutex_unlock( &thelock->mut );
437-
CHECK_STATUS("pthread_mutex_unlock[1]");
438448

439449
if (error) success = 0;
440450
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));

0 commit comments

Comments
 (0)