提交 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): ...@@ -242,35 +242,9 @@ class SubProcess(object):
""" """
self.cmd = cmd self.cmd = cmd
self.verbose = verbose 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.allow_output_check = allow_output_check
self.start_time = time.time() self.result = CmdResult(self.cmd)
self.result = CmdResult(cmd) self._popen = None
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)
def __str__(self): def __str__(self):
if self.result.exit_status is None: if self.result.exit_status is None:
...@@ -279,6 +253,36 @@ class SubProcess(object): ...@@ -279,6 +253,36 @@ class SubProcess(object):
rc = self.result.exit_status rc = self.result.exit_status
return 'SubProcess(cmd="%s", rc="%s")' % (self.cmd, rc) 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): def _fd_drainer(self, input_pipe):
""" """
Read from input_pipe, storing and logging output. Read from input_pipe, storing and logging output.
...@@ -325,6 +329,7 @@ class SubProcess(object): ...@@ -325,6 +329,7 @@ class SubProcess(object):
lock.release() lock.release()
def _fill_results(self, rc): def _fill_results(self, rc):
self._init_subprocess()
self.result.exit_status = rc self.result.exit_status = rc
if self.result.duration == 0: if self.result.duration == 0:
self.result.duration = time.time() - self.start_time self.result.duration = time.time() - self.start_time
...@@ -350,6 +355,7 @@ class SubProcess(object): ...@@ -350,6 +355,7 @@ class SubProcess(object):
:return: Standard output of the process. :return: Standard output of the process.
:rtype: str :rtype: str
""" """
self._init_subprocess()
self.stdout_lock.acquire() self.stdout_lock.acquire()
stdout = self.stdout_file.getvalue() stdout = self.stdout_file.getvalue()
self.stdout_lock.release() self.stdout_lock.release()
...@@ -362,6 +368,7 @@ class SubProcess(object): ...@@ -362,6 +368,7 @@ class SubProcess(object):
:return: Standard error of the process. :return: Standard error of the process.
:rtype: str :rtype: str
""" """
self._init_subprocess()
self.stderr_lock.acquire() self.stderr_lock.acquire()
stderr = self.stderr_file.getvalue() stderr = self.stderr_file.getvalue()
self.stderr_lock.release() self.stderr_lock.release()
...@@ -371,12 +378,14 @@ class SubProcess(object): ...@@ -371,12 +378,14 @@ class SubProcess(object):
""" """
Send a :attr:`signal.SIGTERM` to the process. Send a :attr:`signal.SIGTERM` to the process.
""" """
self._init_subprocess()
self.send_signal(signal.SIGTERM) self.send_signal(signal.SIGTERM)
def kill(self): def kill(self):
""" """
Send a :attr:`signal.SIGKILL` to the process. Send a :attr:`signal.SIGKILL` to the process.
""" """
self._init_subprocess()
self.send_signal(signal.SIGKILL) self.send_signal(signal.SIGKILL)
def send_signal(self, sig): def send_signal(self, sig):
...@@ -385,12 +394,14 @@ class SubProcess(object): ...@@ -385,12 +394,14 @@ class SubProcess(object):
:param sig: Signal to send. :param sig: Signal to send.
""" """
self._init_subprocess()
self._popen.send_signal(sig) self._popen.send_signal(sig)
def poll(self): def poll(self):
""" """
Call the subprocess poll() method, fill results if rc is not None. Call the subprocess poll() method, fill results if rc is not None.
""" """
self._init_subprocess()
rc = self._popen.poll() rc = self._popen.poll()
if rc is not None: if rc is not None:
self._fill_results(rc) self._fill_results(rc)
...@@ -400,6 +411,7 @@ class SubProcess(object): ...@@ -400,6 +411,7 @@ class SubProcess(object):
""" """
Call the subprocess poll() method, fill results if rc is not None. Call the subprocess poll() method, fill results if rc is not None.
""" """
self._init_subprocess()
rc = self._popen.wait() rc = self._popen.wait()
if rc is not None: if rc is not None:
self._fill_results(rc) self._fill_results(rc)
...@@ -416,6 +428,7 @@ class SubProcess(object): ...@@ -416,6 +428,7 @@ class SubProcess(object):
:returns: The command result object. :returns: The command result object.
:rtype: A :class:`avocado.utils.process.CmdResult` instance. :rtype: A :class:`avocado.utils.process.CmdResult` instance.
""" """
self._init_subprocess()
start_time = time.time() start_time = time.time()
if timeout is None: if timeout is None:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册