提交 dd40a68c 编写于 作者: L Lucas Meneghel Rodrigues

avocado.utils.process: Move subprocess initialization to public method calls

Currently, as soon as we initialize a process.SubProcess
object, a subprocess.Popen() object is created. This breaks
the user's expectation that the process will start when
run() is called. Therefore, move process execution to
a private method, and call that method in all public
methods of the class.
Signed-off-by: NLucas Meneghel Rodrigues <lmr@redhat.com>
上级 2b4b3183
......@@ -242,35 +242,9 @@ class SubProcess(object):
"""
self.cmd = cmd
self.verbose = verbose
if self.verbose:
log.info("Running '%s'", cmd)
self._popen = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
self.allow_output_check = allow_output_check
self.start_time = time.time()
self.result = CmdResult(cmd)
self.stdout_file = StringIO.StringIO()
self.stderr_file = StringIO.StringIO()
self.stdout_lock = threading.Lock()
self.stdout_thread = threading.Thread(target=self._fd_drainer,
name="%s-stdout" % cmd,
args=[self._popen.stdout])
self.stdout_thread.daemon = True
self.stderr_lock = threading.Lock()
self.stderr_thread = threading.Thread(target=self._fd_drainer,
name="%s-stderr" % cmd,
args=[self._popen.stderr])
self.stderr_thread.daemon = True
self.stdout_thread.start()
self.stderr_thread.start()
def signal_handler(signum, frame):
self.result.interrupted = True
self.wait()
signal.signal(signal.SIGINT, signal_handler)
self.result = CmdResult(self.cmd)
self._popen = None
def __str__(self):
if self.result.exit_status is None:
......@@ -279,6 +253,36 @@ class SubProcess(object):
rc = self.result.exit_status
return 'SubProcess(cmd="%s", rc="%s")' % (self.cmd, rc)
def _init_subprocess(self):
if self._popen is None:
if self.verbose:
log.info("Running '%s'", self.cmd)
self._popen = subprocess.Popen(self.cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
self.start_time = time.time()
self.stdout_file = StringIO.StringIO()
self.stderr_file = StringIO.StringIO()
self.stdout_lock = threading.Lock()
self.stdout_thread = threading.Thread(target=self._fd_drainer,
name="%s-stdout" % self.cmd,
args=[self._popen.stdout])
self.stdout_thread.daemon = True
self.stderr_lock = threading.Lock()
self.stderr_thread = threading.Thread(target=self._fd_drainer,
name="%s-stderr" % self.cmd,
args=[self._popen.stderr])
self.stderr_thread.daemon = True
self.stdout_thread.start()
self.stderr_thread.start()
def signal_handler(signum, frame):
self.result.interrupted = True
self.wait()
signal.signal(signal.SIGINT, signal_handler)
def _fd_drainer(self, input_pipe):
"""
Read from input_pipe, storing and logging output.
......@@ -325,6 +329,7 @@ class SubProcess(object):
lock.release()
def _fill_results(self, rc):
self._init_subprocess()
self.result.exit_status = rc
if self.result.duration == 0:
self.result.duration = time.time() - self.start_time
......@@ -350,6 +355,7 @@ class SubProcess(object):
:return: Standard output of the process.
:rtype: str
"""
self._init_subprocess()
self.stdout_lock.acquire()
stdout = self.stdout_file.getvalue()
self.stdout_lock.release()
......@@ -362,6 +368,7 @@ class SubProcess(object):
:return: Standard error of the process.
:rtype: str
"""
self._init_subprocess()
self.stderr_lock.acquire()
stderr = self.stderr_file.getvalue()
self.stderr_lock.release()
......@@ -371,12 +378,14 @@ class SubProcess(object):
"""
Send a :attr:`signal.SIGTERM` to the process.
"""
self._init_subprocess()
self.send_signal(signal.SIGTERM)
def kill(self):
"""
Send a :attr:`signal.SIGKILL` to the process.
"""
self._init_subprocess()
self.send_signal(signal.SIGKILL)
def send_signal(self, sig):
......@@ -385,12 +394,14 @@ class SubProcess(object):
:param sig: Signal to send.
"""
self._init_subprocess()
self._popen.send_signal(sig)
def poll(self):
"""
Call the subprocess poll() method, fill results if rc is not None.
"""
self._init_subprocess()
rc = self._popen.poll()
if rc is not None:
self._fill_results(rc)
......@@ -400,6 +411,7 @@ class SubProcess(object):
"""
Call the subprocess poll() method, fill results if rc is not None.
"""
self._init_subprocess()
rc = self._popen.wait()
if rc is not None:
self._fill_results(rc)
......@@ -416,6 +428,7 @@ class SubProcess(object):
:returns: The command result object.
:rtype: A :class:`avocado.utils.process.CmdResult` instance.
"""
self._init_subprocess()
start_time = time.time()
if timeout is None:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册