summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Larson <chris_larson@mentor.com>2012-10-29 20:01:23 (GMT)
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-12-07 17:25:54 (GMT)
commit3b9a640f8d19cd50d64ae2722304ace80453149e (patch)
treec62c9a85e3dea9580d1d88b0579594c6e57ac524
parenta2100b9b9d06c88f3791620729f64c39f8443f64 (diff)
downloadpoky-3b9a640f8d19cd50d64ae2722304ace80453149e.tar.gz
bitbake: command: add error to return of runCommand
Currently, command.py can return an error message from runCommand, due to being unable to run the command, yet few of our UIs (just hob) can handle it today. This can result in seeing a TypeError with traceback in certain rare circumstances. To resolve this, we need a clean way to get errors back from runCommand, without having to isinstance() the return value. This implements such a thing by making runCommand also return an error (or None if no error occurred). As runCommand now has a method of returning errors, we can also alter the getCmdLineAction bits such that the returned value is just the action, not an additional message. If a sync command wants to return an error, it raises CommandError(message), and the message will be passed to the caller appropriately. Example Usage: result, error = server.runCommand(...) if error: log.error('Unable to run command: %s' % error) return 1 (Bitbake rev: d1002e33e05d45a7e1bd65d79537419a4057e43a) Signed-off-by: Christopher Larson <chris_larson@mentor.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/command.py43
-rw-r--r--bitbake/lib/bb/server/process.py2
-rw-r--r--bitbake/lib/bb/ui/crumbs/hobeventhandler.py10
-rw-r--r--bitbake/lib/bb/ui/depexp.py38
-rw-r--r--bitbake/lib/bb/ui/goggle.py17
-rw-r--r--bitbake/lib/bb/ui/knotty.py46
-rw-r--r--bitbake/lib/bb/ui/ncurses.py21
7 files changed, 112 insertions, 65 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index 27b5171..3f28bca 100644
--- a/bitbake/lib/bb/command.py
+++ b/bitbake/lib/bb/command.py
@@ -44,6 +44,9 @@ class CommandFailed(CommandExit):
44 self.error = message 44 self.error = message
45 CommandExit.__init__(self, 1) 45 CommandExit.__init__(self, 1)
46 46
47class CommandError(Exception):
48 pass
49
47class Command: 50class Command:
48 """ 51 """
49 A queue of asynchronous commands for bitbake 52 A queue of asynchronous commands for bitbake
@@ -57,21 +60,25 @@ class Command:
57 self.currentAsyncCommand = None 60 self.currentAsyncCommand = None
58 61
59 def runCommand(self, commandline): 62 def runCommand(self, commandline):
60 try: 63 command = commandline.pop(0)
61 command = commandline.pop(0) 64 if hasattr(CommandsSync, command):
62 if command in CommandsSync.__dict__: 65 # Can run synchronous commands straight away
63 # Can run synchronous commands straight away 66 command_method = getattr(self.cmds_sync, command)
64 return getattr(CommandsSync, command)(self.cmds_sync, self, commandline) 67 try:
65 if self.currentAsyncCommand is not None: 68 result = command_method(self, commandline)
66 return "Busy (%s in progress)" % self.currentAsyncCommand[0] 69 except CommandError as exc:
67 if command not in CommandsAsync.__dict__: 70 return None, exc.args[0]
68 return "No such command" 71 except Exception:
69 self.currentAsyncCommand = (command, commandline) 72 return None, traceback.format_exc()
70 self.cooker.server_registration_cb(self.cooker.runCommands, self.cooker) 73 else:
71 return True 74 return result, None
72 except: 75 if self.currentAsyncCommand is not None:
73 import traceback 76 return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
74 return traceback.format_exc() 77 if command not in CommandsAsync.__dict__:
78 return None, "No such command"
79 self.currentAsyncCommand = (command, commandline)
80 self.cooker.server_registration_cb(self.cooker.runCommands, self.cooker)
81 return True, None
75 82
76 def runAsyncCommand(self): 83 def runAsyncCommand(self):
77 try: 84 try:
@@ -139,7 +146,11 @@ class CommandsSync:
139 """ 146 """
140 Get any command parsed from the commandline 147 Get any command parsed from the commandline
141 """ 148 """
142 return command.cooker.commandlineAction 149 cmd_action = command.cooker.commandlineAction
150 if cmd_action['msg']:
151 raise CommandError(msg)
152 else:
153 return cmd_action['action']
143 154
144 def getVariable(self, command, params): 155 def getVariable(self, command, params):
145 """ 156 """
diff --git a/bitbake/lib/bb/server/process.py b/bitbake/lib/bb/server/process.py
index ba91336..3ae9ede 100644
--- a/bitbake/lib/bb/server/process.py
+++ b/bitbake/lib/bb/server/process.py
@@ -48,7 +48,7 @@ class ServerCommunicator():
48 if self.connection.poll(.5): 48 if self.connection.poll(.5):
49 return self.connection.recv() 49 return self.connection.recv()
50 else: 50 else:
51 return None 51 return None, "Timeout while attempting to communicate with bitbake server"
52 except KeyboardInterrupt: 52 except KeyboardInterrupt:
53 pass 53 pass
54 54
diff --git a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
index 5d038f4..82ebc7d 100644
--- a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
+++ b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
@@ -101,13 +101,9 @@ class HobHandler(gobject.GObject):
101 101
102 def runCommand(self, commandline): 102 def runCommand(self, commandline):
103 try: 103 try:
104 result = self.server.runCommand(commandline) 104 result, error = self.server.runCommand(commandline)
105 result_str = str(result) 105 if error:
106 if (result_str.startswith("Busy (") or 106 raise Exception("Error running command '%s': %s" % (commandline, error))
107 result_str == "No such command"):
108 raise Exception('%s has failed with output "%s". ' %
109 (str(commandline), result_str) +
110 "We recommend that you restart Hob.")
111 return result 107 return result
112 except Exception as e: 108 except Exception as e:
113 self.commands_async = [] 109 self.commands_async = []
diff --git a/bitbake/lib/bb/ui/depexp.py b/bitbake/lib/bb/ui/depexp.py
index 1a716a8..85910f6 100644
--- a/bitbake/lib/bb/ui/depexp.py
+++ b/bitbake/lib/bb/ui/depexp.py
@@ -198,17 +198,23 @@ class gtkthread(threading.Thread):
198 198
199def main(server, eventHandler): 199def main(server, eventHandler):
200 try: 200 try:
201 cmdline = server.runCommand(["getCmdLineAction"]) 201 cmdline, error = server.runCommand(["getCmdLineAction"])
202 if cmdline and not cmdline['action']: 202 if error:
203 print(cmdline['msg']) 203 print("Error getting bitbake commandline: %s" % error)
204 return 204 return 1
205 elif not cmdline or (cmdline['action'] and cmdline['action'][0] != "generateDotGraph"): 205 elif not cmdline:
206 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
207 return 1
208 elif not cmdline or cmdline[0] != "generateDotGraph":
206 print("This UI is only compatible with the -g option") 209 print("This UI is only compatible with the -g option")
207 return 210 return 1
208 ret = server.runCommand(["generateDepTreeEvent", cmdline['action'][1], cmdline['action'][2]]) 211 ret, error = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
209 if ret != True: 212 if error:
210 print("Couldn't run command! %s" % ret) 213 print("Error running command '%s': %s" % (cmdline, error))
211 return 214 return 1
215 elif ret != True:
216 print("Error running command '%s': returned %s" % (cmdline, ret))
217 return 1
212 except xmlrpclib.Fault as x: 218 except xmlrpclib.Fault as x:
213 print("XMLRPC Fault getting commandline:\n %s" % x) 219 print("XMLRPC Fault getting commandline:\n %s" % x)
214 return 220 return
@@ -234,7 +240,9 @@ def main(server, eventHandler):
234 try: 240 try:
235 event = eventHandler.waitEvent(0.25) 241 event = eventHandler.waitEvent(0.25)
236 if gtkthread.quit.isSet(): 242 if gtkthread.quit.isSet():
237 server.runCommand(["stateStop"]) 243 _, error = server.runCommand(["stateStop"])
244 if error:
245 print('Unable to cleanly stop: %s' % error)
238 break 246 break
239 247
240 if event is None: 248 if event is None:
@@ -310,9 +318,13 @@ def main(server, eventHandler):
310 break 318 break
311 if shutdown == 1: 319 if shutdown == 1:
312 print("\nSecond Keyboard Interrupt, stopping...\n") 320 print("\nSecond Keyboard Interrupt, stopping...\n")
313 server.runCommand(["stateStop"]) 321 _, error = server.runCommand(["stateStop"])
322 if error:
323 print('Unable to cleanly stop: %s' % error)
314 if shutdown == 0: 324 if shutdown == 0:
315 print("\nKeyboard Interrupt, closing down...\n") 325 print("\nKeyboard Interrupt, closing down...\n")
316 server.runCommand(["stateShutdown"]) 326 _, error = server.runCommand(["stateShutdown"])
327 if error:
328 print('Unable to cleanly shutdown: %s' % error)
317 shutdown = shutdown + 1 329 shutdown = shutdown + 1
318 pass 330 pass
diff --git a/bitbake/lib/bb/ui/goggle.py b/bitbake/lib/bb/ui/goggle.py
index b2fd274..c0785b7 100644
--- a/bitbake/lib/bb/ui/goggle.py
+++ b/bitbake/lib/bb/ui/goggle.py
@@ -80,16 +80,19 @@ def main (server, eventHandler):
80 running_build.connect ("build-failed", running_build_failed_cb) 80 running_build.connect ("build-failed", running_build_failed_cb)
81 81
82 try: 82 try:
83 cmdline = server.runCommand(["getCmdLineAction"]) 83 cmdline, error = server.runCommand(["getCmdLineAction"])
84 if not cmdline: 84 if err:
85 print("Error getting bitbake commandline: %s" % error)
86 return 1
87 elif not cmdline:
85 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") 88 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
86 return 1 89 return 1
87 elif not cmdline['action']: 90 ret, error = server.runCommand(cmdline)
88 print(cmdline['msg']) 91 if error:
92 print("Error running command '%s': %s" % (cmdline, error))
89 return 1 93 return 1
90 ret = server.runCommand(cmdline['action']) 94 elif ret != True:
91 if ret != True: 95 print("Error running command '%s': returned %s" % (cmdline, ret))
92 print("Couldn't get default commandline! %s" % ret)
93 return 1 96 return 1
94 except xmlrpclib.Fault as x: 97 except xmlrpclib.Fault as x:
95 print("XMLRPC Fault getting commandline:\n %s" % x) 98 print("XMLRPC Fault getting commandline:\n %s" % x)
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 3799018..8c63d74 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -217,9 +217,19 @@ class TerminalFilter(object):
217def main(server, eventHandler, tf = TerminalFilter): 217def main(server, eventHandler, tf = TerminalFilter):
218 218
219 # Get values of variables which control our output 219 # Get values of variables which control our output
220 includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"]) 220 includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
221 loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"]) 221 if error:
222 consolelogfile = server.runCommand(["getVariable", "BB_CONSOLELOG"]) 222 logger.error("Unable to get the value of BBINCLUDELOGS variable: %s" % error)
223 return 1
224 loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
225 if error:
226 logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
227 return 1
228 consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
229 if error:
230 logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
231 return 1
232
223 if sys.stdin.isatty() and sys.stdout.isatty(): 233 if sys.stdin.isatty() and sys.stdout.isatty():
224 log_exec_tty = True 234 log_exec_tty = True
225 else: 235 else:
@@ -240,19 +250,22 @@ def main(server, eventHandler, tf = TerminalFilter):
240 logger.addHandler(consolelog) 250 logger.addHandler(consolelog)
241 251
242 try: 252 try:
243 cmdline = server.runCommand(["getCmdLineAction"]) 253 cmdline, error = server.runCommand(["getCmdLineAction"])
244 if not cmdline: 254 if error:
255 logger.error("Unable to get bitbake commandline arguments: %s" % error)
256 return 1
257 elif not cmdline:
245 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") 258 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
246 return 1 259 return 1
247 elif not cmdline['action']: 260 ret, error = server.runCommand(cmdline)
248 print(cmdline['msg']) 261 if error:
262 logger.error("Command '%s' failed: %s" % (cmdline, error))
249 return 1 263 return 1
250 ret = server.runCommand(cmdline['action']) 264 elif ret != True:
251 if ret != True: 265 logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
252 print("Couldn't get default commandline! %s" % ret)
253 return 1 266 return 1
254 except xmlrpclib.Fault as x: 267 except xmlrpclib.Fault as x:
255 print("XMLRPC Fault getting commandline:\n %s" % x) 268 logger.error("XMLRPC Fault getting commandline:\n %s" % x)
256 return 1 269 return 1
257 270
258 parseprogress = None 271 parseprogress = None
@@ -447,14 +460,19 @@ def main(server, eventHandler, tf = TerminalFilter):
447 if ioerror.args[0] == 4: 460 if ioerror.args[0] == 4:
448 pass 461 pass
449 except KeyboardInterrupt: 462 except KeyboardInterrupt:
463 import time
450 termfilter.clearFooter() 464 termfilter.clearFooter()
451 if main.shutdown == 1: 465 if main.shutdown == 1:
452 print("\nSecond Keyboard Interrupt, stopping...\n") 466 print("\nSecond Keyboard Interrupt, stopping...\n")
453 server.runCommand(["stateStop"]) 467 _, error = server.runCommand(["stateStop"])
468 if error:
469 logger.error("Unable to cleanly stop: %s" % error)
454 if main.shutdown == 0: 470 if main.shutdown == 0:
455 interrupted = True
456 print("\nKeyboard Interrupt, closing down...\n") 471 print("\nKeyboard Interrupt, closing down...\n")
457 server.runCommand(["stateShutdown"]) 472 interrupted = True
473 _, error = server.runCommand(["stateShutdown"])
474 if error:
475 logger.error("Unable to cleanly shutdown: %s" % error)
458 main.shutdown = main.shutdown + 1 476 main.shutdown = main.shutdown + 1
459 pass 477 pass
460 478
diff --git a/bitbake/lib/bb/ui/ncurses.py b/bitbake/lib/bb/ui/ncurses.py
index f6ea7f9..98647fc 100644
--- a/bitbake/lib/bb/ui/ncurses.py
+++ b/bitbake/lib/bb/ui/ncurses.py
@@ -236,15 +236,18 @@ class NCursesUI:
236 shutdown = 0 236 shutdown = 0
237 237
238 try: 238 try:
239 cmdline = server.runCommand(["getCmdLineAction"]) 239 cmdline, error = server.runCommand(["getCmdLineAction"])
240 if not cmdline: 240 if not cmdline:
241 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") 241 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
242 return 242 return
243 elif not cmdline['action']: 243 elif error:
244 print(cmdline['msg']) 244 print("Error getting bitbake commandline: %s" % error)
245 return 245 return
246 ret = server.runCommand(cmdline['action']) 246 ret, error = server.runCommand(cmdline)
247 if ret != True: 247 if error:
248 print("Error running command '%s': %s" % (cmdline, error))
249 return
250 elif ret != True:
248 print("Couldn't get default commandlind! %s" % ret) 251 print("Couldn't get default commandlind! %s" % ret)
249 return 252 return
250 except xmlrpclib.Fault as x: 253 except xmlrpclib.Fault as x:
@@ -345,10 +348,14 @@ class NCursesUI:
345 exitflag = True 348 exitflag = True
346 if shutdown == 1: 349 if shutdown == 1:
347 mw.appendText("Second Keyboard Interrupt, stopping...\n") 350 mw.appendText("Second Keyboard Interrupt, stopping...\n")
348 server.runCommand(["stateStop"]) 351 _, error = server.runCommand(["stateStop"])
352 if error:
353 print("Unable to cleanly stop: %s" % error)
349 if shutdown == 0: 354 if shutdown == 0:
350 mw.appendText("Keyboard Interrupt, closing down...\n") 355 mw.appendText("Keyboard Interrupt, closing down...\n")
351 server.runCommand(["stateShutdown"]) 356 _, error = server.runCommand(["stateShutdown"])
357 if error:
358 print("Unable to cleanly shutdown: %s" % error)
352 shutdown = shutdown + 1 359 shutdown = shutdown + 1
353 pass 360 pass
354 361