1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

utils/misc: Cleanup check_output()

* Remove check_output_lock as the issue has been fixed in Python 3.4
* Use Popen process as a context manager. Technically,
  Popen.communicate() already achieves those but the context manager
  will ensure this is done even if an exception happens at any point.
This commit is contained in:
Douglas Raillard 2022-08-12 18:25:11 +01:00 committed by Marc Bonnici
parent be734140b3
commit 678822f9e4

View File

@ -151,22 +151,16 @@ 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.RLock()
def get_subprocess(command, **kwargs): def get_subprocess(command, **kwargs):
if 'stdout' in kwargs: if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.') raise ValueError('stdout argument not allowed, it will be overridden.')
with check_output_lock: return subprocess.Popen(command,
process = subprocess.Popen(command, stdout=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE,
stdin=subprocess.PIPE, preexec_fn=preexec_function,
preexec_fn=preexec_function, **kwargs)
**kwargs)
return process
def check_subprocess_output(process, timeout=None, ignore=None, inputtext=None): def check_subprocess_output(process, timeout=None, ignore=None, inputtext=None):
@ -181,21 +175,22 @@ def check_subprocess_output(process, timeout=None, ignore=None, inputtext=None):
message = 'Invalid value for ignore parameter: "{}"; must be an int or a list' message = 'Invalid value for ignore parameter: "{}"; must be an int or a list'
raise ValueError(message.format(ignore)) raise ValueError(message.format(ignore))
try: with process:
output, error = process.communicate(inputtext, timeout=timeout) try:
except subprocess.TimeoutExpired as e: output, error = process.communicate(inputtext, timeout=timeout)
timeout_expired = e except subprocess.TimeoutExpired as e:
else: timeout_expired = e
timeout_expired = None else:
timeout_expired = None
# Currently errors=replace is needed as 0x8c throws an error # Currently errors=replace is needed as 0x8c throws an error
output = output.decode(sys.stdout.encoding or 'utf-8', "replace") if output else '' output = output.decode(sys.stdout.encoding or 'utf-8', "replace") if output else ''
error = error.decode(sys.stderr.encoding or 'utf-8', "replace") if error else '' error = error.decode(sys.stderr.encoding or 'utf-8', "replace") if error else ''
if timeout_expired: if timeout_expired:
raise TimeoutError(process.args, output='\n'.join([output, error])) raise TimeoutError(process.args, output='\n'.join([output, error]))
retcode = process.poll() retcode = process.returncode
if retcode and ignore != 'all' and retcode not in ignore: if retcode and ignore != 'all' and retcode not in ignore:
raise subprocess.CalledProcessError(retcode, process.args, output, error) raise subprocess.CalledProcessError(retcode, process.args, output, error)