mirror of
				https://github.com/ARM-software/devlib.git
				synced 2025-10-31 14:01:20 +00:00 
			
		
		
		
	utis/misc: make check_output thread-safe
subprocess.Popen (used internally by check_output) is not thread-safe and may cause a thread to lock up if called simultaneously from multiple threads. See https://bugs.python.org/issue12739 This is fixed in Python 3.2, but since we're currently still on 2.7, work around the issue by protecting the call with a lock.
This commit is contained in:
		
				
					committed by
					
						 Marc Bonnici
						Marc Bonnici
					
				
			
			
				
	
			
			
			
						parent
						
							b88b400d8d
						
					
				
				
					commit
					87b235638a
				
			| @@ -30,6 +30,7 @@ import pkgutil | |||||||
| import logging | import logging | ||||||
| import random | import random | ||||||
| import ctypes | import ctypes | ||||||
|  | import threading | ||||||
| from operator import itemgetter | from operator import itemgetter | ||||||
| from itertools import groupby | from itertools import groupby | ||||||
| from functools import partial | from functools import partial | ||||||
| @@ -135,6 +136,9 @@ def preexec_function(): | |||||||
|  |  | ||||||
|  |  | ||||||
| check_output_logger = logging.getLogger('check_output') | check_output_logger = logging.getLogger('check_output') | ||||||
|  | # Popen is not thread safe. If two threads attempt to call it at the same time, | ||||||
|  | # one may lock up. See https://bugs.python.org/issue12739. | ||||||
|  | check_output_lock = threading.Lock() | ||||||
|  |  | ||||||
|  |  | ||||||
| def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs): | def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs): | ||||||
| @@ -158,9 +162,13 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs): | |||||||
|         except OSError: |         except OSError: | ||||||
|             pass  # process may have already terminated. |             pass  # process may have already terminated. | ||||||
|  |  | ||||||
|     process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |     with check_output_lock: | ||||||
|  |         process = subprocess.Popen(command, | ||||||
|  |                                    stdout=subprocess.PIPE, | ||||||
|  |                                    stderr=subprocess.PIPE, | ||||||
|                                    stdin=subprocess.PIPE, |                                    stdin=subprocess.PIPE, | ||||||
|                                preexec_fn=preexec_function, **kwargs) |                                    preexec_fn=preexec_function, | ||||||
|  |                                    **kwargs) | ||||||
|  |  | ||||||
|     if timeout: |     if timeout: | ||||||
|         timer = threading.Timer(timeout, callback, [process.pid, ]) |         timer = threading.Timer(timeout, callback, [process.pid, ]) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user