def _run_handlers(self, data): """Run handlers attached to this signal and clean source afterwards.""" signal = data.signal source = data.source handlers = data.handlers if not self._force_quit: try: for handler in handlers: handler.callback(signal, handler.data) except ExitMainLoop: self._quit_all_loops() except Exception: # pylint: disable=broad-except self.enqueue_signal(ExceptionSignal(self)) # based on GLib documentation we should clean source # source will be removed from event loop context this way source.destroy() self._mark_signal_processed(signal)
def _process_screen(self): """Draws the current screen and returns True if user input is requested. If modal screen is requested, starts a new loop and initiates redraw after it ends. """ top_screen = self._get_last_screen() log.debug("Processing screen %s", top_screen) # this screen is used first time (call setup() method) if not top_screen.ui_screen.screen_ready: if not top_screen.ui_screen.setup(top_screen.args): # remove the screen and skip if setup went wrong self._screen_stack.pop() self.redraw() log.warning("Screen %s setup wasn't successful", top_screen) return # get the widget tree from the screen and show it in the screen try: # refresh screen content top_screen.ui_screen.refresh(top_screen.args) # Screen was closed in the refresh method if top_screen != self._get_last_screen(): return # draw screen to the console self._draw_screen(top_screen) if top_screen.ui_screen.input_required: log.debug("Input is required by %s screen", top_screen) top_screen.ui_screen.get_input_with_error_check( top_screen.args) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except self._event_loop.enqueue_signal(ExceptionSignal(self)) return False
def process_input(self, user_input): """Process input from the screens. :param user_input: User input string. :type user_input: String. :raises: ExitMainLoop or any other kind of exception from screen processing. """ # process the input, if it wasn't processed (valid) # increment the error counter try: result = self._process_input(user_input) except ExitMainLoop: # pylint: disable=try-except-raise raise except Exception: # pylint: disable=broad-except App.get_event_loop().enqueue_signal(ExceptionSignal(self)) return if result.was_successful(): self._input_error_counter = 0 else: self._input_error_counter += 1 App.get_scheduler().process_input_result(result, self.input_error_threshold_exceeded)
def handleException(self, dump_info): """ Our own handleException method doing some additional stuff before calling the original python-meh's one. :type dump_info: an instance of the meh.DumpInfo class :see: python-meh's ExceptionHandler.handleException """ log.debug("running handleException") exception_lines = traceback.format_exception(*dump_info.exc_info) log.critical("\n".join(exception_lines)) ty = dump_info.exc_info.type value = dump_info.exc_info.value try: gi.require_version("Gtk", "3.0") from gi.repository import Gtk # XXX: Gtk stopped raising RuntimeError if it fails to # initialize. Horay! But will it stay like this? Let's be # cautious and raise the exception on our own to work in both # cases initialized = Gtk.init_check(None)[0] if not initialized: raise RuntimeError() # Attempt to grab the GUI initializing lock, do not block if not self._gui_lock.acquire(False): # the graphical interface is running, don't crash it by # running another one potentially from a different thread log.debug( "Gtk running, queuing exception handler to the main loop") run_in_loop(self._main_loop_handleException, dump_info) else: log.debug( "Gtk not running, starting Gtk and running exception handler in it" ) self._main_loop_handleException(dump_info) except (RuntimeError, ImportError, ValueError): log.debug("Gtk cannot be initialized") # X not running (Gtk cannot be initialized) if threadMgr.in_main_thread(): log.debug("In the main thread, running exception handler") if issubclass(ty, NonInteractiveError) or not self._interactive: if issubclass(ty, NonInteractiveError): cmdline_error_msg = _( "\nThe installation was stopped due to an " "error which occurred while running in " "non-interactive cmdline mode. Since there " "cannot be any questions in cmdline mode, edit " "your kickstart file and retry installation. " "\nThe exact error message is: \n\n%s. \n\nThe " "installer will now terminate.") % str(value) else: cmdline_error_msg = _( "\nRunning in cmdline mode, no interactive " "debugging allowed.\nThe exact error message is: " "\n\n%s.\n\nThe installer will now terminate." ) % str(value) # since there is no UI in cmdline mode and it is completely # non-interactive, we can't show a message window asking the user # to acknowledge the error; instead, print the error out and sleep # for a few seconds before exiting the installer print(cmdline_error_msg) time.sleep(180) sys.exit(1) else: print("\nAn unknown error has occured, look at the " "/tmp/anaconda-tb* file(s) for more details") # in the main thread, run exception handler self._main_loop_handleException(dump_info) else: log.debug( "In a non-main thread, sending a message with exception data" ) # not in the main thread, just send message with exception # data and let message handler run the exception handler in # the main thread exc_info = dump_info.exc_info # new Simpleline package is now used in TUI. Look if Simpleline is # initialized or if this is some fallback from GTK or other stuff. if App.is_initialized(): # if Simpleline is initialized enqueue exception there loop = App.get_event_loop() loop.enqueue_signal( ExceptionSignal(App.get_scheduler(), exception_info=exc_info)) else: hubQ.send_exception( (exc_info.type, exc_info.value, exc_info.stack))