summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/lib/bb/build.py50
-rw-r--r--bitbake/lib/bb/process.py25
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
67def _logged_communicate(pipe, log, input): 67def _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
111def run(cmd, input=None, log=None, **options): 130def 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