hob - handle errors more gracefully
cover hob - handle errors more gracefully
This series predominantly focuses on better error handling and keeping the user informed.
The following changes since commit c9dd2592434338bdddb3cc6f42e760c86fa9e6bb:
hob: fix save/restore of toolchain preferences (2011-07-28 10:58:07 -0700)
are available in the git repository at:
git://github.com/incandescant/bitbake hob
https://github.com/incandescant/bitbake/tree/hob
Joshua Lock (8):
ui/crumbs/hobeventhandler: remove unused code
hob: unset busy cursor on exit ui/crumbs/hobeventhandler: emit a signal when there's a fatal-error ui/hob: show error and exit if we receive the fatal-error signal ui/crumbs/hobeventhandler: emit a signal when a command fails ui/crumbs/configurator: tweak addLayerConf return values ui/crumbs/layereditor: if layer adding fails show an explanatory
dialog
hob: remove temporary directory on program shutdown
lib/bb/ui/crumbs/configurator.py | 7 ++- lib/bb/ui/crumbs/hobeventhandler.py | 72 ++++++++++++++++++++++------------ lib/bb/ui/crumbs/layereditor.py | 20 +++++++++- lib/bb/ui/hob.py | 36 +++++++++++++---- 4 files changed, 97 insertions(+), 38 deletions(-)
Signature · 1 line
1.7.6
PATCH 4/8 ui/hob: show error and exit if we receive the fatal-error signal
If we receive the fatal-error signal from the handler display a dialog informing the user of an error and displaying the error message. Dismissing the dialog quits the application.
Fixes [YOCTO #1279]
--- lib/bb/ui/hob.py | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-)
lib/bb/ui/hob.py +16 -0
@@ -115,6 +115,21 @@ class MainWindow (gtk.Window): self.set_busy_cursor(False) gtk.main_quit() + + """ + In the case of a fatal error give the user as much information as possible + and then exit. + """ + def fatal_error_cb(self, handler, errormsg, phase): + lbl = "<b>Error!</b>\nThere was an unrecoverable error during the" + lbl = lbl + " <i>%s</i> phase of BitBake. This must be" % phase + lbl = lbl + " rectified before the GUI will function. The error" + lbl = lbl + " message which which caused this is:\n\n\"%s\"" % errormsg + dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_ERROR) + dialog.add_button("Exit", gtk.RESPONSE_OK) + response = dialog.run() + dialog.destroy() + self.set_busy_cursor(False) gtk.main_quit() def scroll_tv_cb(self, model, path, it, view):
@@ -963,6 +978,7 @@ def main (server, eventHandler): configurator.connect("layers-loaded", layers.load_current_layers) configurator.connect("layers-changed", handler.reload_data) handler.connect("config-found", configurator.configFound) + handler.connect("fatal-error", window.fatal_error_cb) try: # kick the while thing off
Signature · 1 line
1.7.6
PATCH 3/8 ui/crumbs/hobeventhandler: emit a signal when there's a fatal-error
In reply to Joshua LockIf the cooker encounters an error we're unable to proceed so emit a signal so that UI's can notify the user and exit.
--- lib/bb/ui/crumbs/hobeventhandler.py | 23 +++++++++++++++++++++-- 1 files changed, 21 insertions(+), 2 deletions(-)
lib/bb/ui/crumbs/hobeventhandler.py +21 -2
@@ -19,6 +19,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import gobject +import logging progress_total = 0
@@ -49,8 +50,10 @@ class HobHandler(gobject.GObject): "data-generated" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - "error" : (gobject.SIGNAL_RUN_LAST, + "fatal-error" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, + (gobject.TYPE_STRING, + gobject.TYPE_STRING,)), (gobject.TYPE_STRING,)), "reload-triggered" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
@@ -69,6 +72,7 @@ class HobHandler(gobject.GObject): self.build_toolchain_headers = False self.generating = False self.build_queue = [] + self.current_phase = None self.model = taskmodel self.server = server
@@ -127,11 +131,14 @@ class HobHandler(gobject.GObject): # If we're running a build, use the RunningBuild event handler if self.building: + self.current_phase = "building" running_build.handle_event(event) elif isinstance(event, bb.event.TargetsTreeGenerated): + self.current_phase = "data generation" if event._model: self.model.populate(event._model) elif isinstance(event, bb.event.ConfigFilesFound): + self.current_phase = "configuration lookup" var = event._variable if var == "distro": distros = event._values
@@ -146,9 +153,11 @@ class HobHandler(gobject.GObject): sdk_machines.sort() self.emit("sdk-machines-updated", sdk_machines) elif isinstance(event, bb.event.ConfigFilePathFound): + self.current_phase = "configuration lookup" path = event._path self.emit("config-found", path) elif isinstance(event, bb.event.FilesMatchingFound): + self.current_phase = "configuration lookup" # FIXME: hard coding, should at least be a variable shared between # here and the caller if event._pattern == "rootfs_":
@@ -160,25 +169,35 @@ class HobHandler(gobject.GObject): formats.sort() self.emit("package-formats-found", formats) elif isinstance(event, bb.command.CommandCompleted): + self.current_phase = None self.run_next_command() elif isinstance(event, bb.command.CommandFailed): - self.emit("error", event.error) elif isinstance(event, bb.event.CacheLoadStarted): + self.current_phase = "cache loading" bb.ui.crumbs.hobeventhandler.progress_total = event.total pbar.set_text("Loading cache: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total)) elif isinstance(event, bb.event.CacheLoadProgress): + self.current_phase = "cache loading" pbar.set_text("Loading cache: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total)) elif isinstance(event, bb.event.CacheLoadCompleted): + self.current_phase = None pbar.set_text("Loading cache: %s/%s" % (bb.ui.crumbs.hobeventhandler.progress_total, bb.ui.crumbs.hobeventhandler.progress_total)) elif isinstance(event, bb.event.ParseStarted): + self.current_phase = "recipe parsing" if event.total == 0: return bb.ui.crumbs.hobeventhandler.progress_total = event.total pbar.set_text("Processing recipes: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total)) elif isinstance(event, bb.event.ParseProgress): + self.current_phase = "recipe parsing" pbar.set_text("Processing recipes: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total)) elif isinstance(event, bb.event.ParseCompleted): + self.current_phase = None pbar.set_fraction(1.0) + elif isinstance(event, logging.LogRecord): + format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s") + if event.levelno >= format.CRITICAL: + self.emit("fatal-error", event.getMessage(), self.current_phase) return def event_handle_idle_func (self, eventHandler, running_build, pbar):
Signature · 1 line
1.7.6
PATCH 1/8 ui/crumbs/hobeventhandler: remove unused code
In reply to Joshua LockRemove some unused variables and methods.
--- lib/bb/ui/crumbs/hobeventhandler.py | 18 ------------------ 1 files changed, 0 insertions(+), 18 deletions(-)
lib/bb/ui/crumbs/hobeventhandler.py +0 -18
@@ -117,8 +117,6 @@ class HobHandler(gobject.GObject): if self.generating: self.emit("data-generated") self.generating = False - bbpath = self.server.runCommand(["getVariable", "BBPATH"]) - bbfiles = self.server.runCommand(["getVariable", "BBFILES"]) self.server.runCommand(["buildTargets", self.build_queue, "build"]) self.build_queue = [] self.current_command = None
@@ -279,22 +277,6 @@ class HobHandler(gobject.GObject): if self.build_toolchain_headers != enabled: self.build_toolchain_headers = enabled - def queue_image_recipe_path(self, path): - self.build_queue.append(path) - - def build_complete_cb(self, running_build): - if len(self.build_queue) > 0: - next = self.build_queue.pop(0) - if next.endswith('.bb'): - self.build_file(next) - self.building = 'image' - self.build_file(next) - else: - self.build_packages(next.split(" ")) - else: - self.building = None - self.emit("build-complete") - def set_fstypes(self, fstypes): self.server.runCommand(["setVariable", "IMAGE_FSTYPES", fstypes])
Signature · 1 line
1.7.6
PATCH 2/8 hob: unset busy cursor on exit
In reply to Joshua LockPrevent the busy cursor being shown after hob exits if quit is called whilst the busy cursor is set.
--- lib/bb/ui/hob.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
lib/bb/ui/hob.py +5 -0
@@ -110,6 +110,11 @@ class MainWindow (gtk.Window): rep = self.model.get_build_rep() rep.writeRecipe(self.save_path, self.model) + # Prevent the busy cursor being shown after hob exits if quit is called + # whilst the busy cursor is set + self.set_busy_cursor(False) + + gtk.main_quit() gtk.main_quit() def scroll_tv_cb(self, model, path, it, view):
Signature · 1 line
1.7.6
PATCH 5/8 ui/crumbs/hobeventhandler: emit a signal when a command fails
In reply to Joshua LockIf a CommandFailed event is seen emit a signal with the error message.
--- lib/bb/ui/crumbs/hobeventhandler.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
lib/bb/ui/crumbs/hobeventhandler.py +4 -1
@@ -54,11 +54,13 @@ class HobHandler(gobject.GObject): gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING,)), + "command-failed" : (gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, (gobject.TYPE_STRING,)), "reload-triggered" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, - gobject.TYPE_STRING)), + gobject.TYPE_STRING,)), } (CFG_PATH_LOCAL, CFG_PATH_HOB, CFG_PATH_LAYERS, CFG_FILES_DISTRO, CFG_FILES_MACH, CFG_FILES_SDK, FILES_MATCH_CLASS, GENERATE_TGTS, REPARSE_FILES, BUILD_IMAGE) = range(10)
@@ -172,6 +174,7 @@ class HobHandler(gobject.GObject): self.current_phase = None self.run_next_command() elif isinstance(event, bb.command.CommandFailed): + self.emit("command-failed", event.error) elif isinstance(event, bb.event.CacheLoadStarted): self.current_phase = "cache loading" bb.ui.crumbs.hobeventhandler.progress_total = event.total
Signature · 1 line
1.7.6
PATCH 6/8 ui/crumbs/configurator: tweak addLayerConf return values
In reply to Joshua LockUse different return types when adding failed versus when the layer is already enabled.
--- lib/bb/ui/crumbs/configurator.py | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
lib/bb/ui/crumbs/configurator.py +5 -2
@@ -158,11 +158,14 @@ class Configurator(gobject.GObject): def addLayerConf(self, confpath): layerpath = self._splitLayer(confpath) name = self._getLayerName(layerpath) - if name not in self.enabled_layers: + + if not layerpath or not name: + return None, None + elif name not in self.enabled_layers: self.addLayer(name, layerpath) return name, layerpath else: - return None, None + return name, None def addLayer(self, name, path): self.enabled_layers[name] = path
Signature · 1 line
1.7.6
PATCH 7/8 ui/crumbs/layereditor: if layer adding fails show an explanatory dialog
In reply to Joshua LockWhen adding a layer fails try to explain why to the user.
--- lib/bb/ui/crumbs/layereditor.py | 20 ++++++++++++++++++-- 1 files changed, 18 insertions(+), 2 deletions(-)
lib/bb/ui/crumbs/layereditor.py +18 -2
@@ -21,6 +21,7 @@ import gobject import gtk from bb.ui.crumbs.configurator import Configurator +from bb.ui.crumbs.hig import CrumbsDialog class LayerEditor(gtk.Dialog): """
@@ -117,6 +118,12 @@ class LayerEditor(gtk.Dialog): self.find_layer(self) def find_layer(self, parent): + def conf_error(parent, lbl): + dialog = CrumbsDialog(parent, lbl) + dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + response = dialog.run() + dialog.destroy() + dialog = gtk.FileChooserDialog("Add new layer", parent, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_NO,
@@ -128,10 +135,19 @@ class LayerEditor(gtk.Dialog): path = dialog.get_filename() dialog.destroy() + lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path if response == gtk.RESPONSE_YES: # FIXME: verify we've actually got a layer conf? - if path.endswith(".conf"): + if path.endswith("layer.conf"): name, layerpath = self.configurator.addLayerConf(path) - if name: + if name and layerpath: self.newly_added[name] = layerpath self.layer_store.append([name, layerpath, True]) + return + elif name: + return + else: + lbl += "there was a problem parsing the layer.conf." + else: + lbl += "it is not a layer.conf file." + conf_error(parent, lbl)
Signature · 1 line
1.7.6
PATCH 8/8 hob: remove temporary directory on program shutdown
In reply to Joshua LockMove temp directory handling into the HobEventHandler and clean up the temporary files on program close.
Fixes [YOCTO #1307]
--- lib/bb/ui/crumbs/hobeventhandler.py | 26 +++++++++++++++++++++----- lib/bb/ui/hob.py | 15 +++++++-------- 2 files changed, 28 insertions(+), 13 deletions(-)
lib/bb/ui/crumbs/hobeventhandler.py +21 -5
@@ -20,6 +20,8 @@ import gobject import logging +import tempfile +import datetime progress_total = 0
@@ -75,6 +77,7 @@ class HobHandler(gobject.GObject): self.generating = False self.build_queue = [] self.current_phase = None + self.image_dir = None self.model = taskmodel self.server = server
@@ -237,7 +240,7 @@ class HobHandler(gobject.GObject): pmake = "-j %s" % threads self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", pmake]) - def build_image(self, image, image_path, configurator): + def build_image(self, image, configurator): targets = [] targets.append(image) if self.build_toolchain and self.build_toolchain_headers:
@@ -248,24 +251,24 @@ class HobHandler(gobject.GObject): bbpath_ok = False bbpath = self.server.runCommand(["getVariable", "BBPATH"]) - if image_path in bbpath.split(":"): + if self.image_dir in bbpath.split(":"): bbpath_ok = True bbfiles_ok = False bbfiles = self.server.runCommand(["getVariable", "BBFILES"]).split(" ") for files in bbfiles: import re - pattern = "%s/\*.bb" % image_path + pattern = "%s/\*.bb" % self.image_dir if re.match(pattern, files): bbfiles_ok = True if not bbpath_ok: - nbbp = image_path + nbbp = self.image_dir else: nbbp = None if not bbfiles_ok: - nbbf = "%s/*.bb" % image_path + nbbf = "%s/*.bb" % self.image_dir else: nbbf = None
@@ -319,3 +322,16 @@ class HobHandler(gobject.GObject): def get_image_deploy_dir(self): return self.server.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) + + def make_temp_dir(self): + self.image_dir = os.path.join(tempfile.gettempdir(), 'hob-images') + bb.utils.mkdirhier(self.image_dir) + + def remove_temp_dir(self): + bb.utils.remove(self.image_dir, True) + + def get_temp_recipe_path(self, name): + timestamp = datetime.date.today().isoformat() + image_file = "hob-%s-variant-%s.bb" % (name, timestamp) + recipepath = os.path.join(self.image_dir, image_file) + return recipepath
lib/bb/ui/hob.py +7 -8
@@ -114,6 +114,8 @@ class MainWindow (gtk.Window): # whilst the busy cursor is set self.set_busy_cursor(False) + self.handler.remove_temp_dir() + gtk.main_quit() """
@@ -418,13 +420,10 @@ class MainWindow (gtk.Window): rep.base_image = "empty" if build_image: - import tempfile, datetime - - image_name = "hob-%s-variant-%s" % (rep.base_image, datetime.date.today().isoformat()) - image_file = "%s.bb" % (image_name) - image_dir = os.path.join(tempfile.gettempdir(), 'hob-images') - bb.utils.mkdirhier(image_dir) - recipepath = os.path.join(image_dir, image_file) + self.handler.make_temp_dir() + recipepath = self.handler.get_temp_recipe_path(rep.base_image) + image_name = recipepath.rstrip(".bb") + path, sep, image_name = image_name.rpartition("/") rep.writeRecipe(recipepath, self.model) # In the case where we saved the file for the purpose of building
@@ -433,7 +432,7 @@ class MainWindow (gtk.Window): if not self.save_path: self.files_to_clean.append(recipepath) - self.handler.build_image(image_name, image_dir, self.configurator) + self.handler.build_image(image_name, self.configurator) else: self.handler.build_packages(rep.allpkgs.split(" "))
Signature · 1 line
1.7.6
Richard Purdie
AppliedQuoted 22 lines · Joshua Lock
This series predominantly focuses on better error handling and keeping the user informed.
The following changes since commit
c9dd2592434338bdddb3cc6f42e760c86fa9e6bb:hob: fix save/restore of toolchain preferences (2011-07-28 10:58:07 -0700)
are available in the git repository at:
git://github.com/incandescant/bitbakehob
https://github.com/incandescant/bitbake/tree/hobJoshua Lock (8):
ui/crumbs/hobeventhandler: remove unused code
hob: unset busy cursor on exit ui/crumbs/hobeventhandler: emit a signal when there's a fatal-error ui/hob: show error and exit if we receive the fatal-error signal ui/crumbs/hobeventhandler: emit a signal when a command fails ui/crumbs/configurator: tweak addLayerConf return values ui/crumbs/layereditor: if layer adding fails show an explanatory
dialog
hob: remove temporary directory on program shutdown
Quoted 5 lines
lib/bb/ui/crumbs/configurator.py | 7 ++- lib/bb/ui/crumbs/hobeventhandler.py | 72 ++++++++++++++++++++++------------ lib/bb/ui/crumbs/layereditor.py | 20 +++++++++- lib/bb/ui/hob.py | 36 +++++++++++++---- 4 files changed, 97 insertions(+), 38 deletions(-)
Merged to master, thanks.
Richard