1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-02-07 13:40:48 +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:
sergei Trofimov 2018-04-20 10:06:29 +01:00 committed by Marc Bonnici
parent b88b400d8d
commit 87b235638a

View File

@ -30,6 +30,7 @@ import pkgutil
import logging
import random
import ctypes
import threading
from operator import itemgetter
from itertools import groupby
from functools import partial
@ -135,6 +136,9 @@ def preexec_function():
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):
@ -158,9 +162,13 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
except OSError:
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,
preexec_fn=preexec_function, **kwargs)
preexec_fn=preexec_function,
**kwargs)
if timeout:
timer = threading.Timer(timeout, callback, [process.pid, ])