def _show_message_in_main_thread(self, msg_fn, args):
        """
        If running in the main thread, run the message dialog function and
        return its return value. If running in a non-main thread, request the
        message function to be called in the main thread.

        :param msg_fn: message dialog function to be run
        :type msg_fn: a function taking the same number of arguments as is the
                      length of the args param
        :param args: arguments to be passed to the message dialog function
        :type args: any

        """

        if threadMgr.in_main_thread():
            # call the function directly
            return msg_fn(*args)
        else:
            # create a queue for the result returned by the function
            ret_queue = Queue.Queue()

            # request the function to be called in the main thread
            self._send_show_message(msg_fn, args, ret_queue)

            # wait and return the result from the queue
            return ret_queue.get()
    def _call_method(*args, **kwargs):
        """The new body for the decorated method.
        """
        if threadMgr.in_main_thread():
            # nothing special has to be done in the main thread
            func(*args, **kwargs)
            return

        GLib.idle_add(_idle_method, args, kwargs)
Example #3
0
    def _call_method(*args, **kwargs):
        """The new body for the decorated method.
        """
        if threadMgr.in_main_thread():
            # nothing special has to be done in the main thread
            func(*args, **kwargs)
            return

        GLib.idle_add(_idle_method, args, kwargs)
    def _call_method(*args, **kwargs):
        """The new body for the decorated method. If needed, it uses closure
           bound queue_instance variable which is valid until the reference to this
           method is destroyed."""
        if threadMgr.in_main_thread():
            # nothing special has to be done in the main thread
            return func(*args, **kwargs)

        GLib.idle_add(_idle_method, queue_instance, args, kwargs)
        return queue_instance.get()
Example #5
0
    def _call_method(*args, **kwargs):
        """The new body for the decorated method. If needed, it uses closure
           bound queue_instance variable which is valid until the reference to this
           method is destroyed."""
        if threadMgr.in_main_thread():
            # nothing special has to be done in the main thread
            return func(*args, **kwargs)

        GLib.idle_add(_idle_method, queue_instance, args, kwargs)
        return queue_instance.get()
Example #6
0
    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")
                GLib.idle_add(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, CmdlineError) or not self._interactive:
                    if issubclass(ty, CmdlineError):
                        cmdline_error_msg = _(
                            "\nThe installation was stopped due to "
                            "incomplete spokes detected 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(10)
                    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
                hubQ.send_exception((exc_info.type, exc_info.value, exc_info.stack))
def gtk_batch_map(action, items, args=(), pre_func=None, batch_size=1):
    """
    Function that maps an action on items in a way that makes the action run in
    the main thread, but without blocking the main thread for a noticeable
    time. If a pre-processing function is given it is mapped on the items first
    before the action happens in the main thread.

    .. DANGER::
       MUST NOT BE CALLED NOR WAITED FOR FROM THE MAIN THREAD.

    :param action: any action that has to be done on the items in the main
                   thread
    :type action: (action_item, \\*args) -> None
    :param items: an iterable of items that the action should be mapped on
    :type items: iterable
    :param args: additional arguments passed to the action function
    :type args: tuple
    :param pre_func: a function that is mapped on the items before they are
                     passed to the action function
    :type pre_func: item -> action_item
    :param batch_size: how many items should be processed in one run in the main loop
    :raise AssertionError: if called from the main thread
    :return: None

    """

    assert(not threadMgr.in_main_thread())

    def preprocess(queue_instance):
        if pre_func:
            for item in items:
                queue_instance.put(pre_func(item))
        else:
            for item in items:
                queue_instance.put(item)

        queue_instance.put(TERMINATOR)

    def process_one_batch(arguments):
        (queue_instance, action, done_event) = arguments
        tstamp_start = time.time()
        tstamp = time.time()

        # process as many batches as user shouldn't notice
        while tstamp - tstamp_start < NOTICEABLE_FREEZE:
            for _i in range(batch_size):
                try:
                    action_item = queue_instance.get_nowait()
                    if action_item is TERMINATOR:
                        # all items processed, tell we are finished and return
                        done_event.set()
                        return False
                    else:
                        # run action on the item
                        action(action_item, *args)
                except queue.Empty:
                    # empty queue_instance, reschedule to run later
                    return True

            tstamp = time.time()

        # out of time but something left, reschedule to run again later
        return True

    item_queue_instance = queue.Queue()
    done_event = threading.Event()

    # we don't want to log the whole list, type and address is enough
    log.debug("Starting applying %s on %s", action, object.__repr__(items))

    # start a thread putting preprocessed items into the queue_instance
    threadMgr.add(AnacondaThread(prefix="AnaGtkBatchPre",
                                 target=preprocess,
                                 args=(item_queue_instance,)))

    GLib.idle_add(process_one_batch, (item_queue_instance, action, done_event))
    done_event.wait()
    log.debug("Finished applying %s on %s", action, object.__repr__(items))
    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")

        ty = dump_info.exc_info.type
        value = dump_info.exc_info.value

        if (issubclass(ty, blivet.errors.StorageError) and value.hardware_fault) \
                or (issubclass(ty, OSError) and value.errno == errno.EIO):
            # hardware fault or '[Errno 5] Input/Output error'
            hw_error_msg = _("The installation was stopped due to what "
                             "seems to be a problem with your hardware. "
                             "The exact error message is:\n\n%s.\n\n "
                             "The installer will now terminate.") % str(value)
            self.intf.messageWindow(_("Hardware error occured"), hw_error_msg)
            sys.exit(0)
        else:
            try:
                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()

                if Gtk.main_level() > 0:
                    # main loop 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")
                    GLib.idle_add(self.run_handleException, dump_info)
                else:
                    log.debug("Gtk not running, starting Gtk and running "
                             "exception handler in it")
                    super(AnacondaExceptionHandler, self).handleException(
                                                            dump_info)

            except RuntimeError:
                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")
                    print "An unknown error has occured, look at the "\
                        "/tmp/anaconda-tb* file(s) for more details"
                    # in the main thread, run exception handler
                    super(AnacondaExceptionHandler, self).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
                    hubQ.send_exception((exc_info.type,
                                         exc_info.value,
                                         exc_info.stack))
Example #9
0
    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")
                GLib.idle_add(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, CmdlineError) or not self._interactive:
                    if issubclass(ty, CmdlineError):
                        cmdline_error_msg = _(
                            "\nThe installation was stopped due to "
                            "incomplete spokes detected 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(10)
                    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
                hubQ.send_exception(
                    (exc_info.type, exc_info.value, exc_info.stack))
Example #10
0
    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.debug("\n".join(exception_lines))

        ty = dump_info.exc_info.type
        value = dump_info.exc_info.value

        if (issubclass(ty, blivet.errors.StorageError) and value.hardware_fault) \
                or (issubclass(ty, OSError) and value.errno == errno.EIO):
            # hardware fault or '[Errno 5] Input/Output error'
            hw_error_msg = _("The installation was stopped due to what "
                             "seems to be a problem with your hardware. "
                             "The exact error message is:\n\n%s.\n\n "
                             "The installer will now terminate.") % str(value)
            self.intf.messageWindow(_("Hardware error occured"), hw_error_msg)
            sys.exit(0)
        else:
            try:
                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()

                if Gtk.main_level() > 0:
                    # main loop 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")
                    GLib.idle_add(self.run_handleException, dump_info)
                else:
                    log.debug("Gtk not running, starting Gtk and running "
                             "exception handler in it")
                    super(AnacondaExceptionHandler, self).handleException(
                                                            dump_info)

            except (RuntimeError, ImportError):
                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, CmdlineError)):

                        cmdline_error_msg = _("\nThe installation was stopped due to "
                                              "incomplete spokes detected while running "
                                              "in non-interactive cmdline mode. Since there "
                                              "can not 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)

                        # 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(10)
                        sys.exit(0)
                    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
                        super(AnacondaExceptionHandler, self).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
                    hubQ.send_exception((exc_info.type,
                                         exc_info.value,
                                         exc_info.stack))
    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")

        ty = dump_info.exc_info.type
        value = dump_info.exc_info.value

        if (issubclass(ty, blivet.errors.StorageError) and value.hardware_fault) \
                or (issubclass(ty, OSError) and value.errno == errno.EIO):
            # hardware fault or '[Errno 5] Input/Output error'
            hw_error_msg = _("The installation was stopped due to what "
                             "seems to be a problem with your hardware. "
                             "The exact error message is:\n\n%s.\n\n "
                             "The installer will now terminate.") % str(value)
            self.intf.messageWindow(_("Hardware error occured"), hw_error_msg)
            sys.exit(0)
        else:
            try:
                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()

                if Gtk.main_level() > 0:
                    # main loop 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")
                    GLib.idle_add(self.run_handleException, dump_info)
                else:
                    log.debug("Gtk not running, starting Gtk and running "
                              "exception handler in it")
                    super(AnacondaExceptionHandler,
                          self).handleException(dump_info)

            except RuntimeError:
                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")
                    print "An unknown error has occured, look at the "\
                        "/tmp/anaconda-tb* file(s) for more details"
                    # in the main thread, run exception handler
                    super(AnacondaExceptionHandler,
                          self).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
                    hubQ.send_exception(
                        (exc_info.type, exc_info.value, exc_info.stack))
Example #12
0
    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")

        ty = dump_info.exc_info.type
        value = dump_info.exc_info.value

        if issubclass(ty, blivet.errors.StorageError) and value.hardware_fault:
            hw_error_msg = _("The installation was stopped due to what "
                             "seems to be a problem with your hardware. "
                             "The exact error message is:\n\n%s.\n\n "
                             "The installer will now terminate.") % str(value)
            self.intf.messageWindow(_("Hardware error occured"), hw_error_msg)
            sys.exit(0)
        else:
            try:
                # pylint: disable-msg=E0611
                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, args) = Gtk.init_check(None)
                if not initialized:
                    raise RuntimeError()

                if Gtk.main_level() > 0:
                    # main loop 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")
                    GLib.idle_add(self.run_handleException, dump_info)
                else:
                    log.debug("Gtk not running, starting Gtk and running "
                              "exception handler in it")
                    super(AnacondaExceptionHandler,
                          self).handleException(dump_info)

            except RuntimeError:
                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, CmdlineError)):
                        cmdline_error_msg = _(
                            "\nThe installation was stopped due to an "
                            "error which occurred while running in "
                            "non-interactive cmdline mode. Since there can "
                            "not 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)

                        # 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()
                    else:
                        print "An unknown error has occured, look at the "\
                            "/tmp/anaconda-tb* file(s) for more details"
                        # in the main thread, run exception handler
                        super(AnacondaExceptionHandler,
                              self).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
                    hubQ.send_exception(
                        (exc_info.type, exc_info.value, exc_info.stack))
Example #13
0
def gtk_batch_map(action, items, args=(), pre_func=None, batch_size=1):
    """
    Function that maps an action on items in a way that makes the action run in
    the main thread, but without blocking the main thread for a noticeable
    time. If a pre-processing function is given it is mapped on the items first
    before the action happens in the main thread.

    .. DANGER::
       MUST NOT BE CALLED NOR WAITED FOR FROM THE MAIN THREAD.

    :param action: any action that has to be done on the items in the main
                   thread
    :type action: (action_item, \\*args) -> None
    :param items: an iterable of items that the action should be mapped on
    :type items: iterable
    :param args: additional arguments passed to the action function
    :type args: tuple
    :param pre_func: a function that is mapped on the items before they are
                     passed to the action function
    :type pre_func: item -> action_item
    :param batch_size: how many items should be processed in one run in the main loop
    :raise AssertionError: if called from the main thread
    :return: None

    """

    assert (not threadMgr.in_main_thread())

    def preprocess(queue_instance):
        if pre_func:
            for item in items:
                queue_instance.put(pre_func(item))
        else:
            for item in items:
                queue_instance.put(item)

        queue_instance.put(TERMINATOR)

    def process_one_batch(arguments):
        (queue_instance, action, done_event) = arguments
        tstamp_start = time.time()
        tstamp = time.time()

        # process as many batches as user shouldn't notice
        while tstamp - tstamp_start < NOTICEABLE_FREEZE:
            for _i in range(batch_size):
                try:
                    action_item = queue_instance.get_nowait()
                    if action_item is TERMINATOR:
                        # all items processed, tell we are finished and return
                        done_event.set()
                        return False
                    else:
                        # run action on the item
                        action(action_item, *args)
                except queue.Empty:
                    # empty queue_instance, reschedule to run later
                    return True

            tstamp = time.time()

        # out of time but something left, reschedule to run again later
        return True

    item_queue_instance = queue.Queue()
    done_event = threading.Event()

    # we don't want to log the whole list, type and address is enough
    log.debug("Starting applying %s on %s", action, object.__repr__(items))

    # start a thread putting preprocessed items into the queue_instance
    threadMgr.add(
        AnacondaThread(prefix="AnaGtkBatchPre",
                       target=preprocess,
                       args=(item_queue_instance, )))

    GLib.idle_add(process_one_batch, (item_queue_instance, action, done_event))
    done_event.wait()
    log.debug("Finished applying %s on %s", action, object.__repr__(items))