diff options
-rw-r--r-- | lib/bb/build.py | 50 | ||||
-rw-r--r-- | lib/bb/process.py | 25 |
2 files changed, 65 insertions, 10 deletions
diff --git a/lib/bb/build.py b/lib/bb/build.py index 14dc5e061..cce01feba 100644 --- a/lib/bb/build.py +++ b/lib/bb/build.py @@ -329,14 +329,50 @@ exit $? else: logfile = sys.stdout - bb.debug(2, "Executing shell function %s" % func) + def readfifo(data): + lines = data.split('\0') + for line in lines: + splitval = line.split(' ', 1) + cmd = splitval[0] + if len(splitval) > 1: + value = splitval[1] + else: + value = '' + if cmd == 'bbplain': + bb.plain(value) + elif cmd == 'bbnote': + bb.note(value) + elif cmd == 'bbwarn': + bb.warn(value) + elif cmd == 'bberror': + bb.error(value) + elif cmd == 'bbfatal': + # The caller will call exit themselves, so bb.error() is + # what we want here rather than bb.fatal() + bb.error(value) + elif cmd == 'bbdebug': + splitval = value.split(' ', 1) + level = int(splitval[0]) + value = splitval[1] + bb.debug(level, value) - try: - with open(os.devnull, 'r+') as stdin: - bb.process.run(cmd, shell=False, stdin=stdin, log=logfile) - except bb.process.CmdError: - logfn = d.getVar('BB_LOGFILE', True) - raise FuncFailed(func, logfn) + tempdir = d.getVar('T', True) + fifopath = os.path.join(tempdir, 'fifo.%s' % os.getpid()) + if os.path.exists(fifopath): + os.unlink(fifopath) + os.mkfifo(fifopath) + with open(fifopath, 'r+') as fifo: + try: + bb.debug(2, "Executing shell function %s" % func) + + try: + with open(os.devnull, 'r+') as stdin: + bb.process.run(cmd, shell=False, stdin=stdin, log=logfile, extrafiles=[(fifo,readfifo)]) + except bb.process.CmdError: + logfn = d.getVar('BB_LOGFILE', True) + raise FuncFailed(func, logfn) + finally: + os.unlink(fifopath) bb.debug(2, "Shell function %s finished" % func) diff --git a/lib/bb/process.py b/lib/bb/process.py index 8b1aea9a1..d95a03d17 100644 --- a/lib/bb/process.py +++ b/lib/bb/process.py @@ -64,7 +64,7 @@ class Popen(subprocess.Popen): options.update(kwargs) subprocess.Popen.__init__(self, *args, **options) -def _logged_communicate(pipe, log, input): +def _logged_communicate(pipe, log, input, extrafiles): if pipe.stdin: if input is not None: pipe.stdin.write(input) @@ -79,6 +79,19 @@ def _logged_communicate(pipe, log, input): if pipe.stderr is not None: bb.utils.nonblockingfd(pipe.stderr.fileno()) rin.append(pipe.stderr) + for fobj, _ in extrafiles: + bb.utils.nonblockingfd(fobj.fileno()) + rin.append(fobj) + + def readextras(): + for fobj, func in extrafiles: + try: + data = fobj.read() + except IOError as err: + if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK: + data = None + if data is not None: + func(data) try: while pipe.poll() is None: @@ -100,15 +113,21 @@ def _logged_communicate(pipe, log, input): if data is not None: errdata.append(data) log.write(data) + + readextras() + finally: log.flush() + + readextras() + 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): +def run(cmd, input=None, log=None, extrafiles=[], **options): """Convenience function to run a command and return its output, raising an exception when the command fails""" @@ -124,7 +143,7 @@ def run(cmd, input=None, log=None, **options): raise CmdError(cmd, exc) if log: - stdout, stderr = _logged_communicate(pipe, log, input) + stdout, stderr = _logged_communicate(pipe, log, input, extrafiles) else: stdout, stderr = pipe.communicate(input) |