summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/knotty.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/knotty.py')
-rw-r--r--bitbake/lib/bb/ui/knotty.py450
1 files changed, 334 insertions, 116 deletions
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index bd9911cf6f..f86999bb09 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -12,7 +12,6 @@ from __future__ import division
import os
import sys
-import xmlrpc.client as xmlrpclib
import logging
import progressbar
import signal
@@ -22,10 +21,11 @@ import fcntl
import struct
import copy
import atexit
+from itertools import groupby
from bb.ui import uihelper
-featureSet = [bb.cooker.CookerFeatures.SEND_SANITYEVENTS]
+featureSet = [bb.cooker.CookerFeatures.SEND_SANITYEVENTS, bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING]
logger = logging.getLogger("BitBake")
interactive = sys.stdout.isatty()
@@ -35,15 +35,15 @@ class BBProgress(progressbar.ProgressBar):
self.msg = msg
self.extrapos = extrapos
if not widgets:
- widgets = [progressbar.Percentage(), ' ', progressbar.Bar(), ' ',
- progressbar.ETA()]
- self.extrapos = 4
+ widgets = [': ', progressbar.Percentage(), ' ', progressbar.Bar(),
+ ' ', progressbar.ETA()]
+ self.extrapos = 5
if resize_handler:
self._resize_default = resize_handler
else:
self._resize_default = signal.getsignal(signal.SIGWINCH)
- progressbar.ProgressBar.__init__(self, maxval, [self.msg + ": "] + widgets, fd=sys.stdout)
+ progressbar.ProgressBar.__init__(self, maxval, [self.msg] + widgets, fd=sys.stdout)
def _handle_resize(self, signum=None, frame=None):
progressbar.ProgressBar._handle_resize(self, signum, frame)
@@ -110,12 +110,11 @@ def pluralise(singular, plural, qty):
class InteractConsoleLogFilter(logging.Filter):
- def __init__(self, tf, format):
+ def __init__(self, tf):
self.tf = tf
- self.format = format
def filter(self, record):
- if record.levelno == self.format.NOTE and (record.msg.startswith("Running") or record.msg.startswith("recipe ")):
+ if record.levelno == bb.msg.BBLogFormatter.NOTE and (record.msg.startswith("Running") or record.msg.startswith("recipe ")):
return False
self.tf.clearFooter()
return True
@@ -146,12 +145,12 @@ class TerminalFilter(object):
pass
if not cr:
try:
- cr = (env['LINES'], env['COLUMNS'])
+ cr = (os.environ['LINES'], os.environ['COLUMNS'])
except:
cr = (25, 80)
return cr
- def __init__(self, main, helper, console, errconsole, format, quiet):
+ def __init__(self, main, helper, handlers, quiet):
self.main = main
self.helper = helper
self.cuu = None
@@ -180,8 +179,12 @@ class TerminalFilter(object):
new[3] = new[3] & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSADRAIN, new)
curses.setupterm()
- if curses.tigetnum("colors") > 2:
- format.enable_color()
+ if curses.tigetnum("colors") > 2 and os.environ.get('NO_COLOR', '') == '':
+ for h in handlers:
+ try:
+ h.formatter.enable_color()
+ except AttributeError:
+ pass
self.ed = curses.tigetstr("ed")
if self.ed:
self.cuu = curses.tigetstr("cuu")
@@ -197,10 +200,9 @@ class TerminalFilter(object):
self.interactive = False
bb.note("Unable to use interactive mode for this terminal, using fallback")
return
- if console:
- console.addFilter(InteractConsoleLogFilter(self, format))
- if errconsole:
- errconsole.addFilter(InteractConsoleLogFilter(self, format))
+
+ for h in handlers:
+ h.addFilter(InteractConsoleLogFilter(self))
self.main_progress = None
@@ -226,7 +228,9 @@ class TerminalFilter(object):
def keepAlive(self, t):
if not self.cuu:
- print("Bitbake still alive (%ds)" % t)
+ print("Bitbake still alive (no events for %ds). Active tasks:" % t)
+ for t in self.helper.running_tasks:
+ print(t)
sys.stdout.flush()
def updateFooter(self):
@@ -248,58 +252,68 @@ class TerminalFilter(object):
return
tasks = []
for t in runningpids:
+ start_time = activetasks[t].get("starttime", None)
+ if start_time:
+ msg = "%s - %s (pid %s)" % (activetasks[t]["title"], self.elapsed(currenttime - start_time), activetasks[t]["pid"])
+ else:
+ msg = "%s (pid %s)" % (activetasks[t]["title"], activetasks[t]["pid"])
progress = activetasks[t].get("progress", None)
if progress is not None:
pbar = activetasks[t].get("progressbar", None)
rate = activetasks[t].get("rate", None)
- start_time = activetasks[t].get("starttime", None)
if not pbar or pbar.bouncing != (progress < 0):
if progress < 0:
- pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], activetasks[t]["pid"]), 100, widgets=[progressbar.BouncingSlider(), ''], extrapos=2, resize_handler=self.sigwinch_handle)
+ pbar = BBProgress("0: %s" % msg, 100, widgets=[' ', progressbar.BouncingSlider(), ''], extrapos=3, resize_handler=self.sigwinch_handle)
pbar.bouncing = True
else:
- pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], activetasks[t]["pid"]), 100, widgets=[progressbar.Percentage(), ' ', progressbar.Bar(), ''], extrapos=4, resize_handler=self.sigwinch_handle)
+ pbar = BBProgress("0: %s" % msg, 100, widgets=[' ', progressbar.Percentage(), ' ', progressbar.Bar(), ''], extrapos=5, resize_handler=self.sigwinch_handle)
pbar.bouncing = False
activetasks[t]["progressbar"] = pbar
- tasks.append((pbar, progress, rate, start_time))
+ tasks.append((pbar, msg, progress, rate, start_time))
else:
- start_time = activetasks[t].get("starttime", None)
- if start_time:
- tasks.append("%s - %s (pid %s)" % (activetasks[t]["title"], self.elapsed(currenttime - start_time), activetasks[t]["pid"]))
- else:
- tasks.append("%s (pid %s)" % (activetasks[t]["title"], activetasks[t]["pid"]))
+ tasks.append(msg)
if self.main.shutdown:
- content = "Waiting for %s running tasks to finish:" % len(activetasks)
+ content = pluralise("Waiting for %s running task to finish",
+ "Waiting for %s running tasks to finish", len(activetasks))
+ if not self.quiet:
+ content += ':'
print(content)
else:
+ scene_tasks = "%s of %s" % (self.helper.setscene_current, self.helper.setscene_total)
+ cur_tasks = "%s of %s" % (self.helper.tasknumber_current, self.helper.tasknumber_total)
+
+ content = ''
+ if not self.quiet:
+ msg = "Setscene tasks: %s" % scene_tasks
+ content += msg + "\n"
+ print(msg)
+
if self.quiet:
- content = "Running tasks (%s of %s)" % (self.helper.tasknumber_current, self.helper.tasknumber_total)
+ msg = "Running tasks (%s, %s)" % (scene_tasks, cur_tasks)
elif not len(activetasks):
- content = "No currently running tasks (%s of %s)" % (self.helper.tasknumber_current, self.helper.tasknumber_total)
+ msg = "No currently running tasks (%s)" % cur_tasks
else:
- content = "Currently %2s running tasks (%s of %s)" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
+ msg = "Currently %2s running tasks (%s)" % (len(activetasks), cur_tasks)
maxtask = self.helper.tasknumber_total
if not self.main_progress or self.main_progress.maxval != maxtask:
widgets = [' ', progressbar.Percentage(), ' ', progressbar.Bar()]
self.main_progress = BBProgress("Running tasks", maxtask, widgets=widgets, resize_handler=self.sigwinch_handle)
self.main_progress.start(False)
- self.main_progress.setmessage(content)
- progress = self.helper.tasknumber_current - 1
- if progress < 0:
- progress = 0
- content = self.main_progress.update(progress)
+ self.main_progress.setmessage(msg)
+ progress = max(0, self.helper.tasknumber_current - 1)
+ content += self.main_progress.update(progress)
print('')
- lines = 1 + int(len(content) / (self.columns + 1))
- if self.quiet == 0:
- for tasknum, task in enumerate(tasks[:(self.rows - 2)]):
+ lines = self.getlines(content)
+ if not self.quiet:
+ for tasknum, task in enumerate(tasks[:(self.rows - 1 - lines)]):
if isinstance(task, tuple):
- pbar, progress, rate, start_time = task
+ pbar, msg, progress, rate, start_time = task
if not pbar.start_time:
pbar.start(False)
if start_time:
pbar.start_time = start_time
- pbar.setmessage('%s:%s' % (tasknum, pbar.msg.split(':', 1)[1]))
+ pbar.setmessage('%s: %s' % (tasknum, msg))
pbar.setextra(rate)
if progress > -1:
content = pbar.update(progress)
@@ -309,11 +323,17 @@ class TerminalFilter(object):
else:
content = "%s: %s" % (tasknum, task)
print(content)
- lines = lines + 1 + int(len(content) / (self.columns + 1))
+ lines = lines + self.getlines(content)
self.footer_present = lines
self.lastpids = runningpids[:]
self.lastcount = self.helper.tasknumber_current
+ def getlines(self, content):
+ lines = 0
+ for line in content.split("\n"):
+ lines = lines + 1 + int(len(line) / (self.columns + 1))
+ return lines
+
def finish(self):
if self.stdinbackup:
fd = sys.stdin.fileno()
@@ -363,7 +383,11 @@ def _log_settings_from_server(server, observe_only):
if error:
logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
raise BaseException(error)
- return includelogs, loglines, consolelogfile
+ logconfigfile, error = server.runCommand([cmd, "BB_LOGCONFIG"])
+ if error:
+ logger.error("Unable to get the value of BB_LOGCONFIG variable: %s" % error)
+ raise BaseException(error)
+ return includelogs, loglines, consolelogfile, logconfigfile
_evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.LogRecord",
"bb.build.TaskFailed", "bb.build.TaskBase", "bb.event.ParseStarted",
@@ -375,12 +399,178 @@ _evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.Lo
"bb.event.BuildBase", "bb.build.TaskStarted", "bb.build.TaskSucceeded", "bb.build.TaskFailedSilent",
"bb.build.TaskProgress", "bb.event.ProcessStarted", "bb.event.ProcessProgress", "bb.event.ProcessFinished"]
+def drain_events_errorhandling(eventHandler):
+ # We don't have logging setup, we do need to show any events we see before exiting
+ event = True
+ logger = bb.msg.logger_create('bitbake', sys.stdout)
+ while event:
+ event = eventHandler.waitEvent(0)
+ if isinstance(event, logging.LogRecord):
+ logger.handle(event)
+
def main(server, eventHandler, params, tf = TerminalFilter):
- if not params.observe_only:
- params.updateToServer(server, os.environ.copy())
+ try:
+ if not params.observe_only:
+ params.updateToServer(server, os.environ.copy())
+
+ includelogs, loglines, consolelogfile, logconfigfile = _log_settings_from_server(server, params.observe_only)
- includelogs, loglines, consolelogfile = _log_settings_from_server(server, params.observe_only)
+ loglevel, _ = bb.msg.constructLogOptions()
+ except bb.BBHandledException:
+ drain_events_errorhandling(eventHandler)
+ return 1
+ except Exception as e:
+ # bitbake-server comms failure
+ early_logger = bb.msg.logger_create('bitbake', sys.stdout)
+ early_logger.fatal("Attempting to set server environment: %s", e)
+ return 1
+
+ if params.options.quiet == 0:
+ console_loglevel = loglevel
+ elif params.options.quiet > 2:
+ console_loglevel = bb.msg.BBLogFormatter.ERROR
+ else:
+ console_loglevel = bb.msg.BBLogFormatter.WARNING
+
+ logconfig = {
+ "version": 1,
+ "handlers": {
+ "BitBake.console": {
+ "class": "logging.StreamHandler",
+ "formatter": "BitBake.consoleFormatter",
+ "level": console_loglevel,
+ "stream": "ext://sys.stdout",
+ "filters": ["BitBake.stdoutFilter"],
+ ".": {
+ "is_console": True,
+ },
+ },
+ "BitBake.errconsole": {
+ "class": "logging.StreamHandler",
+ "formatter": "BitBake.consoleFormatter",
+ "level": loglevel,
+ "stream": "ext://sys.stderr",
+ "filters": ["BitBake.stderrFilter"],
+ ".": {
+ "is_console": True,
+ },
+ },
+ # This handler can be used if specific loggers should print on
+ # the console at a lower severity than the default. It will
+ # display any messages sent to it that are lower than then
+ # BitBake.console logging level (so as to prevent duplication of
+ # messages). Nothing is attached to this handler by default
+ "BitBake.verbconsole": {
+ "class": "logging.StreamHandler",
+ "formatter": "BitBake.consoleFormatter",
+ "level": 1,
+ "stream": "ext://sys.stdout",
+ "filters": ["BitBake.verbconsoleFilter"],
+ ".": {
+ "is_console": True,
+ },
+ },
+ },
+ "formatters": {
+ # This format instance will get color output enabled by the
+ # terminal
+ "BitBake.consoleFormatter" : {
+ "()": "bb.msg.BBLogFormatter",
+ "format": "%(levelname)s: %(message)s"
+ },
+ # The file log requires a separate instance so that it doesn't get
+ # color enabled
+ "BitBake.logfileFormatter": {
+ "()": "bb.msg.BBLogFormatter",
+ "format": "%(levelname)s: %(message)s"
+ }
+ },
+ "filters": {
+ "BitBake.stdoutFilter": {
+ "()": "bb.msg.LogFilterLTLevel",
+ "level": "ERROR"
+ },
+ "BitBake.stderrFilter": {
+ "()": "bb.msg.LogFilterGEQLevel",
+ "level": "ERROR"
+ },
+ "BitBake.verbconsoleFilter": {
+ "()": "bb.msg.LogFilterLTLevel",
+ "level": console_loglevel
+ },
+ },
+ "loggers": {
+ "BitBake": {
+ "level": loglevel,
+ "handlers": ["BitBake.console", "BitBake.errconsole"],
+ }
+ },
+ "disable_existing_loggers": False
+ }
+
+ # Enable the console log file if enabled
+ if consolelogfile and not params.options.show_environment and not params.options.show_versions:
+ logconfig = bb.msg.mergeLoggingConfig(logconfig, {
+ "version": 1,
+ "handlers" : {
+ "BitBake.consolelog": {
+ "class": "logging.FileHandler",
+ "formatter": "BitBake.logfileFormatter",
+ "level": loglevel,
+ "filename": consolelogfile,
+ },
+ # Just like verbconsole, anything sent here will go to the
+ # log file, unless it would go to BitBake.consolelog
+ "BitBake.verbconsolelog" : {
+ "class": "logging.FileHandler",
+ "formatter": "BitBake.logfileFormatter",
+ "level": 1,
+ "filename": consolelogfile,
+ "filters": ["BitBake.verbconsolelogFilter"],
+ },
+ },
+ "filters": {
+ "BitBake.verbconsolelogFilter": {
+ "()": "bb.msg.LogFilterLTLevel",
+ "level": loglevel,
+ },
+ },
+ "loggers": {
+ "BitBake": {
+ "handlers": ["BitBake.consolelog"],
+ },
+
+ # Other interesting things that we want to keep an eye on
+ # in the log files in case someone has an issue, but not
+ # necessarily show to the user on the console
+ "BitBake.SigGen.HashEquiv": {
+ "level": "VERBOSE",
+ "handlers": ["BitBake.verbconsolelog"],
+ },
+ "BitBake.RunQueue.HashEquiv": {
+ "level": "VERBOSE",
+ "handlers": ["BitBake.verbconsolelog"],
+ }
+ }
+ })
+
+ bb.utils.mkdirhier(os.path.dirname(consolelogfile))
+ loglink = os.path.join(os.path.dirname(consolelogfile), 'console-latest.log')
+ bb.utils.remove(loglink)
+ try:
+ os.symlink(os.path.basename(consolelogfile), loglink)
+ except OSError:
+ pass
+
+ # Add the logging domains specified by the user on the command line
+ for (domainarg, iterator) in groupby(params.debug_domains):
+ dlevel = len(tuple(iterator))
+ l = logconfig["loggers"].setdefault("BitBake.%s" % domainarg, {})
+ l["level"] = logging.DEBUG - dlevel + 1
+ l.setdefault("handlers", []).extend(["BitBake.verbconsole"])
+
+ conf = bb.msg.setLoggingConfig(logconfig, logconfigfile)
if sys.stdin.isatty() and sys.stdout.isatty():
log_exec_tty = True
@@ -389,23 +579,9 @@ def main(server, eventHandler, params, tf = TerminalFilter):
helper = uihelper.BBUIHelper()
- console = logging.StreamHandler(sys.stdout)
- errconsole = logging.StreamHandler(sys.stderr)
- format_str = "%(levelname)s: %(message)s"
- format = bb.msg.BBLogFormatter(format_str)
- if params.options.quiet == 0:
- forcelevel = None
- elif params.options.quiet > 2:
- forcelevel = bb.msg.BBLogFormatter.ERROR
- else:
- forcelevel = bb.msg.BBLogFormatter.WARNING
- bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut, forcelevel)
- bb.msg.addDefaultlogFilter(errconsole, bb.msg.BBLogFilterStdErr)
- console.setFormatter(format)
- errconsole.setFormatter(format)
- if not bb.msg.has_console_handler(logger):
- logger.addHandler(console)
- logger.addHandler(errconsole)
+ # Look for the specially designated handlers which need to be passed to the
+ # terminal handler
+ console_handlers = [h for h in conf.config['handlers'].values() if getattr(h, 'is_console', False)]
bb.utils.set_process_name("KnottyUI")
@@ -413,27 +589,26 @@ def main(server, eventHandler, params, tf = TerminalFilter):
server.terminateServer()
return
- consolelog = None
- if consolelogfile and not params.options.show_environment and not params.options.show_versions:
- bb.utils.mkdirhier(os.path.dirname(consolelogfile))
- conlogformat = bb.msg.BBLogFormatter(format_str)
- consolelog = logging.FileHandler(consolelogfile)
- bb.msg.addDefaultlogFilter(consolelog)
- consolelog.setFormatter(conlogformat)
- logger.addHandler(consolelog)
- loglink = os.path.join(os.path.dirname(consolelogfile), 'console-latest.log')
- bb.utils.remove(loglink)
- try:
- os.symlink(os.path.basename(consolelogfile), loglink)
- except OSError:
- pass
-
llevel, debug_domains = bb.msg.constructLogOptions()
- server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ try:
+ server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure
+ logger.fatal("Attempting to set event mask: %s", e)
+ return 1
+
+ # The logging_tree module is *extremely* helpful in debugging logging
+ # domains. Uncomment here to dump the logging tree when bitbake starts
+ #import logging_tree
+ #logging_tree.printout()
universe = False
if not params.observe_only:
- params.updateFromServer(server)
+ try:
+ params.updateFromServer(server)
+ except Exception as e:
+ logger.fatal("Fetching command line: %s", e)
+ return 1
cmdline = params.parseActions()
if not cmdline:
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
@@ -444,11 +619,16 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]:
universe = True
- ret, error = server.runCommand(cmdline['action'])
+ try:
+ ret, error = server.runCommand(cmdline['action'])
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure
+ logger.fatal("Command '{}' failed: %s".format(cmdline), e)
+ return 1
if error:
logger.error("Command '%s' failed: %s" % (cmdline, error))
return 1
- elif ret != True:
+ elif not ret:
logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
return 1
@@ -462,25 +642,40 @@ def main(server, eventHandler, params, tf = TerminalFilter):
warnings = 0
taskfailures = []
- printinterval = 5000
- lastprint = time.time()
+ printintervaldelta = 10 * 60 # 10 minutes
+ printinterval = printintervaldelta
+ pinginterval = 1 * 60 # 1 minute
+ lastevent = lastprint = time.time()
- termfilter = tf(main, helper, console, errconsole, format, params.options.quiet)
+ termfilter = tf(main, helper, console_handlers, params.options.quiet)
atexit.register(termfilter.finish)
- while True:
+ # shutdown levels
+ # 0 - normal operation
+ # 1 - no new task execution, let current running tasks finish
+ # 2 - interrupting currently executing tasks
+ # 3 - we're done, exit
+ while main.shutdown < 3:
try:
if (lastprint + printinterval) <= time.time():
termfilter.keepAlive(printinterval)
- printinterval += 5000
+ printinterval += printintervaldelta
event = eventHandler.waitEvent(0)
if event is None:
- if main.shutdown > 1:
- break
- termfilter.updateFooter()
+ if (lastevent + pinginterval) <= time.time():
+ ret, error = server.runCommand(["ping"])
+ if error or not ret:
+ termfilter.clearFooter()
+ print("No reply after pinging server (%s, %s), exiting." % (str(error), str(ret)))
+ return_value = 3
+ main.shutdown = 3
+ lastevent = time.time()
+ if not parseprogress:
+ termfilter.updateFooter()
event = eventHandler.waitEvent(0.25)
if event is None:
continue
+ lastevent = time.time()
helper.eventHandler(event)
if isinstance(event, bb.runqueue.runQueueExitWait):
if not main.shutdown:
@@ -502,27 +697,27 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if isinstance(event, logging.LogRecord):
lastprint = time.time()
- printinterval = 5000
- if event.levelno >= format.ERROR:
+ printinterval = printintervaldelta
+ if event.levelno >= bb.msg.BBLogFormatter.ERRORONCE:
errors = errors + 1
return_value = 1
- elif event.levelno == format.WARNING:
+ elif event.levelno == bb.msg.BBLogFormatter.WARNING:
warnings = warnings + 1
if event.taskpid != 0:
# For "normal" logging conditions, don't show note logs from tasks
# but do show them if the user has changed the default log level to
# include verbose/debug messages
- if event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
+ if event.levelno <= bb.msg.BBLogFormatter.NOTE and (event.levelno < llevel or (event.levelno == bb.msg.BBLogFormatter.NOTE and llevel != bb.msg.BBLogFormatter.VERBOSE)):
continue
# Prefix task messages with recipe/task
- if event.taskpid in helper.pidmap and event.levelno != format.PLAIN:
+ if event.taskpid in helper.pidmap and event.levelno not in [bb.msg.BBLogFormatter.PLAIN, bb.msg.BBLogFormatter.WARNONCE, bb.msg.BBLogFormatter.ERRORONCE]:
taskinfo = helper.running_tasks[helper.pidmap[event.taskpid]]
event.msg = taskinfo['title'] + ': ' + event.msg
- if hasattr(event, 'fn'):
+ if hasattr(event, 'fn') and event.levelno not in [bb.msg.BBLogFormatter.WARNONCE, bb.msg.BBLogFormatter.ERRORONCE]:
event.msg = event.fn + ': ' + event.msg
- logger.handle(event)
+ logging.getLogger(event.name).handle(event)
continue
if isinstance(event, bb.build.TaskFailedSilent):
@@ -539,6 +734,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
if event.total == 0:
continue
+ termfilter.clearFooter()
parseprogress = new_progress("Parsing recipes", event.total).start()
continue
if isinstance(event, bb.event.ParseProgress):
@@ -555,7 +751,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if not parseprogress:
continue
parseprogress.finish()
- pasreprogress = None
+ parseprogress = None
if params.options.quiet == 0:
print(("Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
% ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
@@ -584,14 +780,15 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if event.error:
errors = errors + 1
logger.error(str(event))
- main.shutdown = 2
+ main.shutdown = 3
continue
if isinstance(event, bb.command.CommandExit):
if not return_value:
return_value = event.exitcode
+ main.shutdown = 3
continue
if isinstance(event, (bb.command.CommandCompleted, bb.cooker.CookerExit)):
- main.shutdown = 2
+ main.shutdown = 3
continue
if isinstance(event, bb.event.MultipleProviders):
logger.info(str(event))
@@ -607,7 +804,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
- logger.info("Running setscene task %d of %d (%s)" % (event.stats.completed + event.stats.active + event.stats.failed + 1, event.stats.total, event.taskstring))
+ logger.info("Running setscene task %d of %d (%s)" % (event.stats.setscene_covered + event.stats.setscene_active + event.stats.setscene_notcovered + 1, event.stats.setscene_total, event.taskstring))
continue
if isinstance(event, bb.runqueue.runQueueTaskStarted):
@@ -638,6 +835,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if isinstance(event, bb.event.ProcessStarted):
if params.options.quiet > 1:
continue
+ termfilter.clearFooter()
parseprogress = new_progress(event.processname, event.total)
parseprogress.start(False)
continue
@@ -675,15 +873,26 @@ def main(server, eventHandler, params, tf = TerminalFilter):
logger.error("Unknown event: %s", event)
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure, don't attempt further comms and exit
+ logger.fatal("Executing event: %s", e)
+ return_value = 1
+ errors = errors + 1
+ main.shutdown = 3
except EnvironmentError as ioerror:
termfilter.clearFooter()
# ignore interrupted io
if ioerror.args[0] == 4:
continue
sys.stderr.write(str(ioerror))
- if not params.observe_only:
- _, error = server.runCommand(["stateForceShutdown"])
main.shutdown = 2
+ if not params.observe_only:
+ try:
+ _, error = server.runCommand(["stateForceShutdown"])
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure, don't attempt further comms and exit
+ logger.fatal("Unable to force shutdown: %s", e)
+ main.shutdown = 3
except KeyboardInterrupt:
termfilter.clearFooter()
if params.observe_only:
@@ -692,9 +901,13 @@ def main(server, eventHandler, params, tf = TerminalFilter):
def state_force_shutdown():
print("\nSecond Keyboard Interrupt, stopping...\n")
- _, error = server.runCommand(["stateForceShutdown"])
- if error:
- logger.error("Unable to cleanly stop: %s" % error)
+ try:
+ _, error = server.runCommand(["stateForceShutdown"])
+ if error:
+ logger.error("Unable to cleanly stop: %s" % error)
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure
+ logger.fatal("Unable to cleanly stop: %s", e)
if not params.observe_only and main.shutdown == 1:
state_force_shutdown()
@@ -707,17 +920,24 @@ def main(server, eventHandler, params, tf = TerminalFilter):
_, error = server.runCommand(["stateShutdown"])
if error:
logger.error("Unable to cleanly shutdown: %s" % error)
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure
+ logger.fatal("Unable to cleanly shutdown: %s", e)
except KeyboardInterrupt:
state_force_shutdown()
main.shutdown = main.shutdown + 1
- pass
except Exception as e:
import traceback
sys.stderr.write(traceback.format_exc())
- if not params.observe_only:
- _, error = server.runCommand(["stateForceShutdown"])
main.shutdown = 2
+ if not params.observe_only:
+ try:
+ _, error = server.runCommand(["stateForceShutdown"])
+ except (BrokenPipeError, EOFError) as e:
+ # bitbake-server comms failure, don't attempt further comms and exit
+ logger.fatal("Unable to force shutdown: %s", e)
+ main.shudown = 3
return_value = 1
try:
termfilter.clearFooter()
@@ -728,11 +948,11 @@ def main(server, eventHandler, params, tf = TerminalFilter):
for failure in taskfailures:
summary += "\n %s" % failure
if warnings:
- summary += pluralise("\nSummary: There was %s WARNING message shown.",
- "\nSummary: There were %s WARNING messages shown.", warnings)
+ summary += pluralise("\nSummary: There was %s WARNING message.",
+ "\nSummary: There were %s WARNING messages.", warnings)
if return_value and errors:
- summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
- "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
+ summary += pluralise("\nSummary: There was %s ERROR message, returning a non-zero exit code.",
+ "\nSummary: There were %s ERROR messages, returning a non-zero exit code.", errors)
if summary and params.options.quiet == 0:
print(summary)
@@ -745,8 +965,6 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if e.errno == errno.EPIPE:
pass
- if consolelog:
- logger.removeHandler(consolelog)
- consolelog.close()
+ logging.shutdown()
return return_value