mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 10:26:02 +00:00 
			
		
		
		
	bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked not to (#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
This commit is contained in:
		
							parent
							
								
									63f54c6893
								
							
						
					
					
						commit
						f84ac420c2
					
				
					 2 changed files with 50 additions and 43 deletions
				
			
		|  | @ -0,0 +1,2 @@ | ||||||
|  | Avoid blocking in pthread_mutex_lock() when PyThread_acquire_lock() is asked | ||||||
|  | not to block. | ||||||
|  | @ -466,21 +466,27 @@ PyLockStatus | ||||||
| PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | ||||||
|                             int intr_flag) |                             int intr_flag) | ||||||
| { | { | ||||||
|     PyLockStatus success; |     PyLockStatus success = PY_LOCK_FAILURE; | ||||||
|     pthread_lock *thelock = (pthread_lock *)lock; |     pthread_lock *thelock = (pthread_lock *)lock; | ||||||
|     int status, error = 0; |     int status, error = 0; | ||||||
| 
 | 
 | ||||||
|     dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", |     dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", | ||||||
|              lock, microseconds, intr_flag)); |              lock, microseconds, intr_flag)); | ||||||
| 
 | 
 | ||||||
|  |     if (microseconds == 0) { | ||||||
|  |         status = pthread_mutex_trylock( &thelock->mut ); | ||||||
|  |         if (status != EBUSY) | ||||||
|  |             CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]"); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|         status = pthread_mutex_lock( &thelock->mut ); |         status = pthread_mutex_lock( &thelock->mut ); | ||||||
|         CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]"); |         CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]"); | ||||||
| 
 |     } | ||||||
|  |     if (status == 0) { | ||||||
|         if (thelock->locked == 0) { |         if (thelock->locked == 0) { | ||||||
|             success = PY_LOCK_ACQUIRED; |             success = PY_LOCK_ACQUIRED; | ||||||
|     } else if (microseconds == 0) { |         } | ||||||
|         success = PY_LOCK_FAILURE; |         else if (microseconds != 0) { | ||||||
|     } else { |  | ||||||
|             struct timespec ts; |             struct timespec ts; | ||||||
|             if (microseconds > 0) |             if (microseconds > 0) | ||||||
|                 MICROSECONDS_TO_TIMESPEC(microseconds, ts); |                 MICROSECONDS_TO_TIMESPEC(microseconds, ts); | ||||||
|  | @ -488,7 +494,6 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | ||||||
| 
 | 
 | ||||||
|             /* mut must be locked by me -- part of the condition
 |             /* mut must be locked by me -- part of the condition
 | ||||||
|              * protocol */ |              * protocol */ | ||||||
|         success = PY_LOCK_FAILURE; |  | ||||||
|             while (success == PY_LOCK_FAILURE) { |             while (success == PY_LOCK_FAILURE) { | ||||||
|                 if (microseconds > 0) { |                 if (microseconds > 0) { | ||||||
|                     status = pthread_cond_timedwait( |                     status = pthread_cond_timedwait( | ||||||
|  | @ -511,16 +516,16 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | ||||||
|                      * it and retry.  */ |                      * it and retry.  */ | ||||||
|                     success = PY_LOCK_INTR; |                     success = PY_LOCK_INTR; | ||||||
|                     break; |                     break; | ||||||
|             } else if (status == 0 && !thelock->locked) { |                 } | ||||||
|  |                 else if (status == 0 && !thelock->locked) { | ||||||
|                     success = PY_LOCK_ACQUIRED; |                     success = PY_LOCK_ACQUIRED; | ||||||
|             } else { |  | ||||||
|                 success = PY_LOCK_FAILURE; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (success == PY_LOCK_ACQUIRED) thelock->locked = 1; |         if (success == PY_LOCK_ACQUIRED) thelock->locked = 1; | ||||||
|         status = pthread_mutex_unlock( &thelock->mut ); |         status = pthread_mutex_unlock( &thelock->mut ); | ||||||
|         CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]"); |         CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (error) success = PY_LOCK_FAILURE; |     if (error) success = PY_LOCK_FAILURE; | ||||||
|     dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", |     dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Antoine Pitrou
						Antoine Pitrou