diff options
| -rw-r--r-- | bitbake/lib/bb/build.py | 50 | ||||
| -rw-r--r-- | bitbake/lib/bb/process.py | 25 |
2 files changed, 65 insertions, 10 deletions
diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py index 14dc5e0619..cce01feba2 100644 --- a/bitbake/lib/bb/build.py +++ b/bitbake/lib/bb/build.py | |||
| @@ -329,14 +329,50 @@ exit $? | |||
| 329 | else: | 329 | else: |
| 330 | logfile = sys.stdout | 330 | logfile = sys.stdout |
| 331 | 331 | ||
| 332 | bb.debug(2, "Executing shell function %s" % func) | 332 | def readfifo(data): |
| 333 | lines = data.split('\0') | ||
| 334 | for line in lines: | ||
| 335 | splitval = line.split(' ', 1) | ||
| 336 | cmd = splitval[0] | ||
| 337 | if len(splitval) > 1: | ||
| 338 | value = splitval[1] | ||
| 339 | else: | ||
| 340 | value = '' | ||
| 341 | if cmd == 'bbplain': | ||
| 342 | bb.plain(value) | ||
| 343 | elif cmd == 'bbnote': | ||
| 344 | bb.note(value) | ||
| 345 | elif cmd == 'bbwarn': | ||
| 346 | bb.warn(value) | ||
| 347 | elif cmd == 'bberror': | ||
| 348 | bb.error(value) | ||
| 349 | elif cmd == 'bbfatal': | ||
| 350 | # The caller will call exit themselves, so bb.error() is | ||
| 351 | # what we want here rather than bb.fatal() | ||
| 352 | bb.error(value) | ||
| 353 | elif cmd == 'bbdebug': | ||
| 354 | splitval = value.split(' ', 1) | ||
| 355 | level = int(splitval[0]) | ||
| 356 | value = splitval[1] | ||
| 357 | bb.debug(level, value) | ||
| 333 | 358 | ||
| 334 | try: | 359 | tempdir = d.getVar('T', True) |
| 335 | with open(os.devnull, 'r+') as stdin: | 360 | fifopath = os.path.join(tempdir, 'fifo.%s' % os.getpid()) |
| 336 | bb.process.run(cmd, shell=False, stdin=stdin, log=logfile) | 361 | if os.path.exists(fifopath): |
| 337 | except bb.process.CmdError: | 362 | os.unlink(fifopath) |
| 338 | logfn = d.getVar('BB_LOGFILE', True) | 363 | os.mkfifo(fifopath) |
| 339 | raise FuncFailed(func, logfn) | 364 | with open(fifopath, 'r+') as fifo: |
| 365 | try: | ||
| 366 | bb.debug(2, "Executing shell function %s" % func) | ||
| 367 | |||
| 368 | try: | ||
| 369 | with open(os.devnull, 'r+') as stdin: | ||
| 370 | bb.process.run(cmd, shell=False, stdin=stdin, log=logfile, extrafiles=[(fifo,readfifo)]) | ||
| 371 | except bb.process.CmdError: | ||
| 372 | logfn = d.getVar('BB_LOGFILE', True) | ||
| 373 | raise FuncFailed(func, logfn) | ||
| 374 | finally: | ||
| 375 | os.unlink(fifopath) | ||
| 340 | 376 | ||
| 341 | bb.debug(2, "Shell function %s finished" % func) | 377 | bb.debug(2, "Shell function %s finished" % func) |
| 342 | 378 | ||
diff --git a/bitbake/lib/bb/process.py b/bitbake/lib/bb/process.py index 8b1aea9a10..d95a03d176 100644 --- a/bitbake/lib/bb/process.py +++ b/bitbake/lib/bb/process.py | |||
| @@ -64,7 +64,7 @@ class Popen(subprocess.Popen): | |||
| 64 | options.update(kwargs) | 64 | options.update(kwargs) |
| 65 | subprocess.Popen.__init__(self, *args, **options) | 65 | subprocess.Popen.__init__(self, *args, **options) |
| 66 | 66 | ||
| 67 | def _logged_communicate(pipe, log, input): | 67 | def _logged_communicate(pipe, log, input, extrafiles): |
| 68 | if pipe.stdin: | 68 | if pipe.stdin: |
| 69 | if input is not None: | 69 | if input is not None: |
| 70 | pipe.stdin.write(input) | 70 | pipe.stdin.write(input) |
| @@ -79,6 +79,19 @@ def _logged_communicate(pipe, log, input): | |||
| 79 | if pipe.stderr is not None: | 79 | if pipe.stderr is not None: |
| 80 | bb.utils.nonblockingfd(pipe.stderr.fileno()) | 80 | bb.utils.nonblockingfd(pipe.stderr.fileno()) |
| 81 | rin.append(pipe.stderr) | 81 | rin.append(pipe.stderr) |
| 82 | for fobj, _ in extrafiles: | ||
| 83 | bb.utils.nonblockingfd(fobj.fileno()) | ||
| 84 | rin.append(fobj) | ||
| 85 | |||
| 86 | def readextras(): | ||
| 87 | for fobj, func in extrafiles: | ||
| 88 | try: | ||
| 89 | data = fobj.read() | ||
| 90 | except IOError as err: | ||
| 91 | if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK: | ||
| 92 | data = None | ||
| 93 | if data is not None: | ||
| 94 | func(data) | ||
| 82 | 95 | ||
| 83 | try: | 96 | try: |
| 84 | while pipe.poll() is None: | 97 | while pipe.poll() is None: |
| @@ -100,15 +113,21 @@ def _logged_communicate(pipe, log, input): | |||
| 100 | if data is not None: | 113 | if data is not None: |
| 101 | errdata.append(data) | 114 | errdata.append(data) |
| 102 | log.write(data) | 115 | log.write(data) |
| 116 | |||
| 117 | readextras() | ||
| 118 | |||
| 103 | finally: | 119 | finally: |
| 104 | log.flush() | 120 | log.flush() |
| 121 | |||
| 122 | readextras() | ||
| 123 | |||
| 105 | if pipe.stdout is not None: | 124 | if pipe.stdout is not None: |
| 106 | pipe.stdout.close() | 125 | pipe.stdout.close() |
| 107 | if pipe.stderr is not None: | 126 | if pipe.stderr is not None: |
| 108 | pipe.stderr.close() | 127 | pipe.stderr.close() |
| 109 | return ''.join(outdata), ''.join(errdata) | 128 | return ''.join(outdata), ''.join(errdata) |
| 110 | 129 | ||
| 111 | def run(cmd, input=None, log=None, **options): | 130 | def run(cmd, input=None, log=None, extrafiles=[], **options): |
| 112 | """Convenience function to run a command and return its output, raising an | 131 | """Convenience function to run a command and return its output, raising an |
| 113 | exception when the command fails""" | 132 | exception when the command fails""" |
| 114 | 133 | ||
| @@ -124,7 +143,7 @@ def run(cmd, input=None, log=None, **options): | |||
| 124 | raise CmdError(cmd, exc) | 143 | raise CmdError(cmd, exc) |
| 125 | 144 | ||
| 126 | if log: | 145 | if log: |
| 127 | stdout, stderr = _logged_communicate(pipe, log, input) | 146 | stdout, stderr = _logged_communicate(pipe, log, input, extrafiles) |
| 128 | else: | 147 | else: |
| 129 | stdout, stderr = pipe.communicate(input) | 148 | stdout, stderr = pipe.communicate(input) |
| 130 | 149 | ||
