mirror of
https://github.com/ARM-software/devlib.git
synced 2025-02-12 07:58:07 +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:
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:
|
||||||
stdin=subprocess.PIPE,
|
process = subprocess.Popen(command,
|
||||||
preexec_fn=preexec_function, **kwargs)
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
preexec_fn=preexec_function,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
if timeout:
|
if timeout:
|
||||||
timer = threading.Timer(timeout, callback, [process.pid, ])
|
timer = threading.Timer(timeout, callback, [process.pid, ])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user