diff options
author | Mark Asselstine <mark.asselstine@windriver.com> | 2023-12-28 16:01:18 -0500 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-01-10 14:02:38 +0000 |
commit | 98c5c96dd3902cdc4a455a9ed46591037ab3f676 (patch) | |
tree | 4a555be1e9110218bb1a25e71cbf83d11b50ecf9 /bitbake/lib/bb/ui/knotty.py | |
parent | bc22d82c2f0c16ee8ad2edeb3bcdfb31db0afa94 (diff) | |
download | poky-98c5c96dd3902cdc4a455a9ed46591037ab3f676.tar.gz |
bitbake: ui/knotty: properly handle exceptions when calling runCommand()
In runCommand() the send() and recv() can fail and raise
BrokenPipeError and EOFError exceptions when the bitbake-server is
unexpectedly terminated. In these cases a python traceback is
currently dumped. Similarly updateFromServer() which calls
runCommand() can also raise these and other exceptions, and currently
lacks proper exception handling resulting in python traceback.
We wrap calls to runCommand() and updateFromServer() in a try/except
block as well as improve the exception handling for updateToServer().
This along with the earlier commit which added text to the
BrokenPipeError and EOFError exceptions in runCommand() to indicate a
bitbake-server termination may have occurred, should improve the user's
ability to understand and handle these errors.
An easy way to trigger each of the runCommand() exceptions is to
'kill -9' bitbake-server before (causes EOFError) or after
(causes BrokenPipeError) the "Loading Cache" stage.
(Bitbake rev: 804d366ee3ddc0f37f0a6c712c8d42db45b119bc)
Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/ui/knotty.py')
-rw-r--r-- | bitbake/lib/bb/ui/knotty.py | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py index 431baa15ef..5a97d040b0 100644 --- a/bitbake/lib/bb/ui/knotty.py +++ b/bitbake/lib/bb/ui/knotty.py | |||
@@ -420,6 +420,11 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
420 | except bb.BBHandledException: | 420 | except bb.BBHandledException: |
421 | drain_events_errorhandling(eventHandler) | 421 | drain_events_errorhandling(eventHandler) |
422 | return 1 | 422 | return 1 |
423 | except Exception as e: | ||
424 | # bitbake-server comms failure | ||
425 | early_logger = bb.msg.logger_create('bitbake', sys.stdout) | ||
426 | early_logger.fatal("Attempting to set server environment: %s", e) | ||
427 | return 1 | ||
423 | 428 | ||
424 | if params.options.quiet == 0: | 429 | if params.options.quiet == 0: |
425 | console_loglevel = loglevel | 430 | console_loglevel = loglevel |
@@ -585,7 +590,12 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
585 | return | 590 | return |
586 | 591 | ||
587 | llevel, debug_domains = bb.msg.constructLogOptions() | 592 | llevel, debug_domains = bb.msg.constructLogOptions() |
588 | server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list]) | 593 | try: |
594 | server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list]) | ||
595 | except (BrokenPipeError, EOFError) as e: | ||
596 | # bitbake-server comms failure | ||
597 | logger.fatal("Attempting to set event mask: %s", e) | ||
598 | return 1 | ||
589 | 599 | ||
590 | # The logging_tree module is *extremely* helpful in debugging logging | 600 | # The logging_tree module is *extremely* helpful in debugging logging |
591 | # domains. Uncomment here to dump the logging tree when bitbake starts | 601 | # domains. Uncomment here to dump the logging tree when bitbake starts |
@@ -594,7 +604,11 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
594 | 604 | ||
595 | universe = False | 605 | universe = False |
596 | if not params.observe_only: | 606 | if not params.observe_only: |
597 | params.updateFromServer(server) | 607 | try: |
608 | params.updateFromServer(server) | ||
609 | except Exception as e: | ||
610 | logger.fatal("Fetching command line: %s", e) | ||
611 | return 1 | ||
598 | cmdline = params.parseActions() | 612 | cmdline = params.parseActions() |
599 | if not cmdline: | 613 | if not cmdline: |
600 | print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") | 614 | print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") |
@@ -605,7 +619,12 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
605 | if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]: | 619 | if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]: |
606 | universe = True | 620 | universe = True |
607 | 621 | ||
608 | ret, error = server.runCommand(cmdline['action']) | 622 | try: |
623 | ret, error = server.runCommand(cmdline['action']) | ||
624 | except (BrokenPipeError, EOFError) as e: | ||
625 | # bitbake-server comms failure | ||
626 | logger.fatal("Command '{}' failed: %s".format(cmdline), e) | ||
627 | return 1 | ||
609 | if error: | 628 | if error: |
610 | logger.error("Command '%s' failed: %s" % (cmdline, error)) | 629 | logger.error("Command '%s' failed: %s" % (cmdline, error)) |
611 | return 1 | 630 | return 1 |
@@ -854,15 +873,26 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
854 | 873 | ||
855 | logger.error("Unknown event: %s", event) | 874 | logger.error("Unknown event: %s", event) |
856 | 875 | ||
876 | except (BrokenPipeError, EOFError) as e: | ||
877 | # bitbake-server comms failure, don't attempt further comms and exit | ||
878 | logger.fatal("Executing event: %s", e) | ||
879 | return_value = 1 | ||
880 | errors = errors + 1 | ||
881 | main.shutdown = 3 | ||
857 | except EnvironmentError as ioerror: | 882 | except EnvironmentError as ioerror: |
858 | termfilter.clearFooter() | 883 | termfilter.clearFooter() |
859 | # ignore interrupted io | 884 | # ignore interrupted io |
860 | if ioerror.args[0] == 4: | 885 | if ioerror.args[0] == 4: |
861 | continue | 886 | continue |
862 | sys.stderr.write(str(ioerror)) | 887 | sys.stderr.write(str(ioerror)) |
863 | if not params.observe_only: | ||
864 | _, error = server.runCommand(["stateForceShutdown"]) | ||
865 | main.shutdown = 2 | 888 | main.shutdown = 2 |
889 | if not params.observe_only: | ||
890 | try: | ||
891 | _, error = server.runCommand(["stateForceShutdown"]) | ||
892 | except (BrokenPipeError, EOFError) as e: | ||
893 | # bitbake-server comms failure, don't attempt further comms and exit | ||
894 | logger.fatal("Unable to force shutdown: %s", e) | ||
895 | main.shutdown = 3 | ||
866 | except KeyboardInterrupt: | 896 | except KeyboardInterrupt: |
867 | termfilter.clearFooter() | 897 | termfilter.clearFooter() |
868 | if params.observe_only: | 898 | if params.observe_only: |
@@ -871,9 +901,13 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
871 | 901 | ||
872 | def state_force_shutdown(): | 902 | def state_force_shutdown(): |
873 | print("\nSecond Keyboard Interrupt, stopping...\n") | 903 | print("\nSecond Keyboard Interrupt, stopping...\n") |
874 | _, error = server.runCommand(["stateForceShutdown"]) | 904 | try: |
875 | if error: | 905 | _, error = server.runCommand(["stateForceShutdown"]) |
876 | logger.error("Unable to cleanly stop: %s" % error) | 906 | if error: |
907 | logger.error("Unable to cleanly stop: %s" % error) | ||
908 | except (BrokenPipeError, EOFError) as e: | ||
909 | # bitbake-server comms failure | ||
910 | logger.fatal("Unable to cleanly stop: %s", e) | ||
877 | 911 | ||
878 | if not params.observe_only and main.shutdown == 1: | 912 | if not params.observe_only and main.shutdown == 1: |
879 | state_force_shutdown() | 913 | state_force_shutdown() |
@@ -886,6 +920,9 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
886 | _, error = server.runCommand(["stateShutdown"]) | 920 | _, error = server.runCommand(["stateShutdown"]) |
887 | if error: | 921 | if error: |
888 | logger.error("Unable to cleanly shutdown: %s" % error) | 922 | logger.error("Unable to cleanly shutdown: %s" % error) |
923 | except (BrokenPipeError, EOFError) as e: | ||
924 | # bitbake-server comms failure | ||
925 | logger.fatal("Unable to cleanly shutdown: %s", e) | ||
889 | except KeyboardInterrupt: | 926 | except KeyboardInterrupt: |
890 | state_force_shutdown() | 927 | state_force_shutdown() |
891 | 928 | ||
@@ -893,9 +930,14 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
893 | except Exception as e: | 930 | except Exception as e: |
894 | import traceback | 931 | import traceback |
895 | sys.stderr.write(traceback.format_exc()) | 932 | sys.stderr.write(traceback.format_exc()) |
896 | if not params.observe_only: | ||
897 | _, error = server.runCommand(["stateForceShutdown"]) | ||
898 | main.shutdown = 2 | 933 | main.shutdown = 2 |
934 | if not params.observe_only: | ||
935 | try: | ||
936 | _, error = server.runCommand(["stateForceShutdown"]) | ||
937 | except (BrokenPipeError, EOFError) as e: | ||
938 | # bitbake-server comms failure, don't attempt further comms and exit | ||
939 | logger.fatal("Unable to force shutdown: %s", e) | ||
940 | main.shudown = 3 | ||
899 | return_value = 1 | 941 | return_value = 1 |
900 | try: | 942 | try: |
901 | termfilter.clearFooter() | 943 | termfilter.clearFooter() |