From c527fd1f14c27855a37f2e8ac5346ce8d940ced2 Mon Sep 17 00:00:00 2001 From: Tudor Florea Date: Thu, 16 Oct 2014 03:05:19 +0200 Subject: initial commit for Enea Linux 4.0-140929 Migrated from the internal git server on the daisy-enea-point-release branch Signed-off-by: Tudor Florea --- bitbake/lib/bb/process.py | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 bitbake/lib/bb/process.py (limited to 'bitbake/lib/bb/process.py') diff --git a/bitbake/lib/bb/process.py b/bitbake/lib/bb/process.py new file mode 100644 index 0000000000..8b1aea9a10 --- /dev/null +++ b/bitbake/lib/bb/process.py @@ -0,0 +1,133 @@ +import logging +import signal +import subprocess +import errno +import select + +logger = logging.getLogger('BitBake.Process') + +def subprocess_setup(): + # Python installs a SIGPIPE handler by default. This is usually not what + # non-Python subprocesses expect. + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + +class CmdError(RuntimeError): + def __init__(self, command, msg=None): + self.command = command + self.msg = msg + + def __str__(self): + if not isinstance(self.command, basestring): + cmd = subprocess.list2cmdline(self.command) + else: + cmd = self.command + + msg = "Execution of '%s' failed" % cmd + if self.msg: + msg += ': %s' % self.msg + return msg + +class NotFoundError(CmdError): + def __str__(self): + return CmdError.__str__(self) + ": command not found" + +class ExecutionError(CmdError): + def __init__(self, command, exitcode, stdout = None, stderr = None): + CmdError.__init__(self, command) + self.exitcode = exitcode + self.stdout = stdout + self.stderr = stderr + + def __str__(self): + message = "" + if self.stderr: + message += self.stderr + if self.stdout: + message += self.stdout + if message: + message = ":\n" + message + return (CmdError.__str__(self) + + " with exit code %s" % self.exitcode + message) + +class Popen(subprocess.Popen): + defaults = { + "close_fds": True, + "preexec_fn": subprocess_setup, + "stdout": subprocess.PIPE, + "stderr": subprocess.STDOUT, + "stdin": subprocess.PIPE, + "shell": False, + } + + def __init__(self, *args, **kwargs): + options = dict(self.defaults) + options.update(kwargs) + subprocess.Popen.__init__(self, *args, **options) + +def _logged_communicate(pipe, log, input): + if pipe.stdin: + if input is not None: + pipe.stdin.write(input) + pipe.stdin.close() + + outdata, errdata = [], [] + rin = [] + + if pipe.stdout is not None: + bb.utils.nonblockingfd(pipe.stdout.fileno()) + rin.append(pipe.stdout) + if pipe.stderr is not None: + bb.utils.nonblockingfd(pipe.stderr.fileno()) + rin.append(pipe.stderr) + + try: + while pipe.poll() is None: + rlist = rin + try: + r,w,e = select.select (rlist, [], [], 1) + except OSError as e: + if e.errno != errno.EINTR: + raise + + if pipe.stdout in r: + data = pipe.stdout.read() + if data is not None: + outdata.append(data) + log.write(data) + + if pipe.stderr in r: + data = pipe.stderr.read() + if data is not None: + errdata.append(data) + log.write(data) + finally: + log.flush() + if pipe.stdout is not None: + pipe.stdout.close() + if pipe.stderr is not None: + pipe.stderr.close() + return ''.join(outdata), ''.join(errdata) + +def run(cmd, input=None, log=None, **options): + """Convenience function to run a command and return its output, raising an + exception when the command fails""" + + if isinstance(cmd, basestring) and not "shell" in options: + options["shell"] = True + + try: + pipe = Popen(cmd, **options) + except OSError as exc: + if exc.errno == 2: + raise NotFoundError(cmd) + else: + raise CmdError(cmd, exc) + + if log: + stdout, stderr = _logged_communicate(pipe, log, input) + else: + stdout, stderr = pipe.communicate(input) + + if pipe.returncode != 0: + raise ExecutionError(cmd, pipe.returncode, stdout, stderr) + return stdout, stderr -- cgit v1.2.3-54-g00ecf