diff options
author | Christopher Larson <chris_larson@mentor.com> | 2012-10-29 13:01:23 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-11-01 11:46:22 +0000 |
commit | c1c20c02a0eb808a099bebfcc7e90188baa22ba4 (patch) | |
tree | fea4ff816120e77b9e8b5bc547703478387e067d /bitbake/lib | |
parent | 99fa251b5696dff77358d514175bbb08802a7a02 (diff) | |
download | poky-c1c20c02a0eb808a099bebfcc7e90188baa22ba4.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: 717831b8315cb3904d9b590e633000bc897e8fb6)
Signed-off-by: Christopher Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/bb/command.py | 43 | ||||
-rw-r--r-- | bitbake/lib/bb/server/process.py | 2 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/hobeventhandler.py | 10 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/depexp.py | 38 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/goggle.py | 17 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/knotty.py | 46 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/ncurses.py | 21 |
7 files changed, 112 insertions, 65 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py index 27b5171a6e..3f28bca257 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 | ||
47 | class CommandError(Exception): | ||
48 | pass | ||
49 | |||
47 | class Command: | 50 | class 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 4eefe01852..f1e8450b12 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 350b00b9ae..5026bf740f 100644 --- a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py +++ b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py | |||
@@ -108,13 +108,9 @@ class HobHandler(gobject.GObject): | |||
108 | 108 | ||
109 | def runCommand(self, commandline): | 109 | def runCommand(self, commandline): |
110 | try: | 110 | try: |
111 | result = self.server.runCommand(commandline) | 111 | result, error = self.server.runCommand(commandline) |
112 | result_str = str(result) | 112 | if error: |
113 | if (result_str.startswith("Busy (") or | 113 | raise Exception("Error running command '%s': %s" % (commandline, error)) |
114 | result_str == "No such command"): | ||
115 | raise Exception('%s has failed with output "%s". ' % | ||
116 | (str(commandline), result_str) + | ||
117 | "We recommend that you restart Hob.") | ||
118 | return result | 114 | return result |
119 | except Exception as e: | 115 | except Exception as e: |
120 | self.commands_async = [] | 116 | self.commands_async = [] |
diff --git a/bitbake/lib/bb/ui/depexp.py b/bitbake/lib/bb/ui/depexp.py index 1a716a88bf..85910f6925 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 | ||
199 | def main(server, eventHandler): | 199 | def 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 b2fd2741aa..c0785b7990 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 6ac3d85b1e..b99a121729 100644 --- a/bitbake/lib/bb/ui/knotty.py +++ b/bitbake/lib/bb/ui/knotty.py | |||
@@ -217,9 +217,19 @@ class TerminalFilter(object): | |||
217 | def main(server, eventHandler, tf = TerminalFilter): | 217 | def 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 f6ea7f9bca..98647fc3e0 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 | ||