summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Larson <chris_larson@mentor.com>2013-01-27 15:41:20 -0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-01-28 12:43:58 +0000
commitf3acb135e723258bd4b6072d5737d52e13d47054 (patch)
tree3ffa0492ceb3cce8c3094e21d239f048caedcc62
parent878ef6a31c2cea4b6a1012f5b5e29a3bc4d01119 (diff)
downloadpoky-f3acb135e723258bd4b6072d5737d52e13d47054.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>
-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.py5
-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.py45
-rw-r--r--bitbake/lib/bb/ui/ncurses.py21
7 files changed, 112 insertions, 59 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index fd8912ab40..00b854e240 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 ba9133639d..3ae9ede6b6 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 52acec1028..21bea236c4 100644
--- a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
+++ b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
@@ -102,7 +102,10 @@ class HobHandler(gobject.GObject):
102 102
103 def runCommand(self, commandline): 103 def runCommand(self, commandline):
104 try: 104 try:
105 return self.server.runCommand(commandline) 105 result, error = self.server.runCommand(commandline)
106 if error:
107 raise Exception("Error running command '%s': %s" % (commandline, error))
108 return result
106 except Exception as e: 109 except Exception as e:
107 self.commands_async = [] 110 self.commands_async = []
108 self.clear_busy() 111 self.clear_busy()
diff --git a/bitbake/lib/bb/ui/depexp.py b/bitbake/lib/bb/ui/depexp.py
index b62adbf851..1254128edd 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
@@ -229,7 +235,9 @@ def main(server, eventHandler):
229 try: 235 try:
230 event = eventHandler.waitEvent(0.25) 236 event = eventHandler.waitEvent(0.25)
231 if gtkthread.quit.isSet(): 237 if gtkthread.quit.isSet():
232 server.runCommand(["stateStop"]) 238 _, error = server.runCommand(["stateStop"])
239 if error:
240 print('Unable to cleanly stop: %s' % error)
233 break 241 break
234 242
235 if event is None: 243 if event is None:
@@ -302,9 +310,13 @@ def main(server, eventHandler):
302 break 310 break
303 if shutdown == 1: 311 if shutdown == 1:
304 print("\nSecond Keyboard Interrupt, stopping...\n") 312 print("\nSecond Keyboard Interrupt, stopping...\n")
305 server.runCommand(["stateStop"]) 313 _, error = server.runCommand(["stateStop"])
314 if error:
315 print('Unable to cleanly stop: %s' % error)
306 if shutdown == 0: 316 if shutdown == 0:
307 print("\nKeyboard Interrupt, closing down...\n") 317 print("\nKeyboard Interrupt, closing down...\n")
308 server.runCommand(["stateShutdown"]) 318 _, error = server.runCommand(["stateShutdown"])
319 if error:
320 print('Unable to cleanly shutdown: %s' % error)
309 shutdown = shutdown + 1 321 shutdown = shutdown + 1
310 pass 322 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 01674169ec..439a792800 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -107,9 +107,18 @@ class TerminalFilter(object):
107def main(server, eventHandler, tf = TerminalFilter): 107def main(server, eventHandler, tf = TerminalFilter):
108 108
109 # Get values of variables which control our output 109 # Get values of variables which control our output
110 includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"]) 110 includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
111 loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"]) 111 if error:
112 consolelogfile = server.runCommand(["getVariable", "BB_CONSOLELOG"]) 112 logger.error("Unable to get the value of BBINCLUDELOGS variable: %s" % error)
113 return 1
114 loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
115 if error:
116 logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
117 return 1
118 consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
119 if error:
120 logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
121 return 1
113 122
114 helper = uihelper.BBUIHelper() 123 helper = uihelper.BBUIHelper()
115 124
@@ -125,19 +134,22 @@ def main(server, eventHandler, tf = TerminalFilter):
125 logger.addHandler(consolelog) 134 logger.addHandler(consolelog)
126 135
127 try: 136 try:
128 cmdline = server.runCommand(["getCmdLineAction"]) 137 cmdline, error = server.runCommand(["getCmdLineAction"])
129 if not cmdline: 138 if error:
139 logger.error("Unable to get bitbake commandline arguments: %s" % error)
140 return 1
141 elif not cmdline:
130 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") 142 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
131 return 1 143 return 1
132 elif not cmdline['action']: 144 ret, error = server.runCommand(cmdline)
133 print(cmdline['msg']) 145 if error:
146 logger.error("Command '%s' failed: %s" % (cmdline, error))
134 return 1 147 return 1
135 ret = server.runCommand(cmdline['action']) 148 elif ret != True:
136 if ret != True: 149 logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
137 print("Couldn't get default commandline! %s" % ret)
138 return 1 150 return 1
139 except xmlrpclib.Fault as x: 151 except xmlrpclib.Fault as x:
140 print("XMLRPC Fault getting commandline:\n %s" % x) 152 logger.error("XMLRPC Fault getting commandline:\n %s" % x)
141 return 1 153 return 1
142 154
143 parseprogress = None 155 parseprogress = None
@@ -318,14 +330,19 @@ def main(server, eventHandler, tf = TerminalFilter):
318 if ioerror.args[0] == 4: 330 if ioerror.args[0] == 4:
319 pass 331 pass
320 except KeyboardInterrupt: 332 except KeyboardInterrupt:
333 import time
321 termfilter.clearFooter() 334 termfilter.clearFooter()
322 if main.shutdown == 1: 335 if main.shutdown == 1:
323 print("\nSecond Keyboard Interrupt, stopping...\n") 336 print("\nSecond Keyboard Interrupt, stopping...\n")
324 server.runCommand(["stateStop"]) 337 _, error = server.runCommand(["stateStop"])
338 if error:
339 logger.error("Unable to cleanly stop: %s" % error)
325 if main.shutdown == 0: 340 if main.shutdown == 0:
326 interrupted = True
327 print("\nKeyboard Interrupt, closing down...\n") 341 print("\nKeyboard Interrupt, closing down...\n")
328 server.runCommand(["stateShutdown"]) 342 interrupted = True
343 _, error = server.runCommand(["stateShutdown"])
344 if error:
345 logger.error("Unable to cleanly shutdown: %s" % error)
329 main.shutdown = main.shutdown + 1 346 main.shutdown = main.shutdown + 1
330 pass 347 pass
331 348
diff --git a/bitbake/lib/bb/ui/ncurses.py b/bitbake/lib/bb/ui/ncurses.py
index 8524446d22..896ed01a78 100644
--- a/bitbake/lib/bb/ui/ncurses.py
+++ b/bitbake/lib/bb/ui/ncurses.py
@@ -230,15 +230,18 @@ class NCursesUI:
230 shutdown = 0 230 shutdown = 0
231 231
232 try: 232 try:
233 cmdline = server.runCommand(["getCmdLineAction"]) 233 cmdline, error = server.runCommand(["getCmdLineAction"])
234 if not cmdline: 234 if not cmdline:
235 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") 235 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
236 return 236 return
237 elif not cmdline['action']: 237 elif error:
238 print(cmdline['msg']) 238 print("Error getting bitbake commandline: %s" % error)
239 return 239 return
240 ret = server.runCommand(cmdline['action']) 240 ret, error = server.runCommand(cmdline)
241 if ret != True: 241 if error:
242 print("Error running command '%s': %s" % (cmdline, error))
243 return
244 elif ret != True:
242 print("Couldn't get default commandlind! %s" % ret) 245 print("Couldn't get default commandlind! %s" % ret)
243 return 246 return
244 except xmlrpclib.Fault as x: 247 except xmlrpclib.Fault as x:
@@ -337,10 +340,14 @@ class NCursesUI:
337 exitflag = True 340 exitflag = True
338 if shutdown == 1: 341 if shutdown == 1:
339 mw.appendText("Second Keyboard Interrupt, stopping...\n") 342 mw.appendText("Second Keyboard Interrupt, stopping...\n")
340 server.runCommand(["stateStop"]) 343 _, error = server.runCommand(["stateStop"])
344 if error:
345 print("Unable to cleanly stop: %s" % error)
341 if shutdown == 0: 346 if shutdown == 0:
342 mw.appendText("Keyboard Interrupt, closing down...\n") 347 mw.appendText("Keyboard Interrupt, closing down...\n")
343 server.runCommand(["stateShutdown"]) 348 _, error = server.runCommand(["stateShutdown"])
349 if error:
350 print("Unable to cleanly shutdown: %s" % error)
344 shutdown = shutdown + 1 351 shutdown = shutdown + 1
345 pass 352 pass
346 353