From 93df477e812e216b8336f8894205902112687251 Mon Sep 17 00:00:00 2001 From: t_feng Date: Sat, 8 May 2021 11:33:58 +0800 Subject: [PATCH] fix-xorg-timeout-and-throw-exception (cherry picked from commit 8d9c3ac436e5d044cc500782af26a02da2feaafd) --- anaconda.spec | 16 +- fix-xorg-timeout-and-throw-exception.patch | 207 +++++++++++++++++++++ 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 fix-xorg-timeout-and-throw-exception.patch diff --git a/anaconda.spec b/anaconda.spec index 661f228..0636f42 100644 --- a/anaconda.spec +++ b/anaconda.spec @@ -1,7 +1,7 @@ %define _empty_manifest_terminate_build 0 Name: anaconda Version: 33.19 -Release: 19 +Release: 21 Summary: Graphical system installer License: GPLv2+ and MIT URL: http://fedoraproject.org/wiki/Anaconda @@ -107,6 +107,8 @@ Patch6067: bugfix-Fix-checking-ssl-certificate-for-metadata-1745064.patch Patch6068: bugfix-Fix-error-in-initrd-shift-count-out-of-range.patch Patch6069: bugfix-Fix-the-logic-for-enabling-latest-updates.patch Patch6070: bugfix-Don-t-enter-spokes-after-we-leave-the-Summary-hub.patch +Patch6071: bugfix-do-not-mount-dbus-source.patch +Patch6072: fix-xorg-timeout-and-throw-exception.patch %define dbusver 1.2.3 %define dnfver 3.6.0 @@ -320,6 +322,18 @@ update-desktop-database &> /dev/null || : %{_datadir}/gtk-doc %changelog +* Sat May 8 2021 fengtao - 33.19-21 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix xorg timeout and throw exception + +* Thu Apr 29 2021 zhangrui - 33.19-20 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:do not mount dbus sources + * Mon Mar 29 2021 xuxiaolong - 33.19-19 - Type:bugfix - ID:NA diff --git a/fix-xorg-timeout-and-throw-exception.patch b/fix-xorg-timeout-and-throw-exception.patch new file mode 100644 index 0000000..43b31ba --- /dev/null +++ b/fix-xorg-timeout-and-throw-exception.patch @@ -0,0 +1,207 @@ +From 0b851a3f25d6e2ac7e6d06e342d0823c206ee25a Mon Sep 17 00:00:00 2001 +From: Vladimir Slavik +Date: Wed, 21 Apr 2021 20:00:54 +0200 +Subject: [PATCH] Another attempt at the X thing. This gives up the exception + handler test temporarily, and solves almost everything. + +The main problem of other solutions is that once X starts, +it steals the screen by going to tty6. If the exception handler +test-invoking handler is not returned back immediately, +an "after-timeout" handler can be installed instead, which switches back to tty1. + +With that in place, it's also safe to terminate Xorg once +it's clear it's not coming in time. The termination will happen later, +but that does not matter any more. + +Finally, with the termination happening, +it is also safe to return the crash report text handler. + +Resolves: rhbz#1918702 + +Previous work: #3107, #3132, #3141, #3295. Thanks to @bitcoffeeiux and @poncovka. + +The one avenue left unexplored is using the -displayfd option. +--- + pyanaconda/core/util.py | 62 ++++++++++++++++++++++++++++++++--------- + pyanaconda/display.py | 29 +++++++++++++++++-- + 2 files changed, 75 insertions(+), 16 deletions(-) + +diff --git a/pyanaconda/core/util.py b/pyanaconda/core/util.py +index b7a1731..3013cd8 100644 +--- a/pyanaconda/core/util.py ++++ b/pyanaconda/core/util.py +@@ -47,7 +47,7 @@ from pyanaconda.core.constants import DRACUT_SHUTDOWN_EJECT, TRANSLATIONS_UPDATE + IPMI_ABORTED, X_TIMEOUT, TAINT_HARDWARE_UNSUPPORTED, TAINT_SUPPORT_REMOVED, \ + WARNING_HARDWARE_UNSUPPORTED, WARNING_SUPPORT_REMOVED + from pyanaconda.core.constants import SCREENSHOTS_DIRECTORY, SCREENSHOTS_TARGET_DIRECTORY +-from pyanaconda.errors import RemovedModuleError, ExitError ++from pyanaconda.errors import RemovedModuleError + + from pyanaconda.anaconda_logging import program_log_lock + from pyanaconda.anaconda_loggers import get_module_logger, get_program_logger +@@ -204,6 +204,19 @@ def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subp + preexec_fn=preexec, cwd=root, env=env, **kwargs) + + ++class X11Status: ++ """Status of Xorg launch. ++ ++ Values of an instance can be modified from the handler functions. ++ """ ++ def __init__(self): ++ self.started = False ++ self.timed_out = False ++ ++ def needs_waiting(self): ++ return not (self.started or self.timed_out) ++ ++ + def startX(argv, output_redirect=None, timeout=X_TIMEOUT): + """ Start X and return once X is ready to accept connections. + +@@ -217,28 +230,36 @@ def startX(argv, output_redirect=None, timeout=X_TIMEOUT): + :param output_redirect: file or file descriptor to redirect stdout and stderr to + :param timeout: Number of seconds to timing out. + """ +- # Use a list so the value can be modified from the handler function +- x11_started = [False] ++ x11_status = X11Status() + +- def sigusr1_handler(num, frame): ++ # Handle successful start before timeout ++ def sigusr1_success_handler(num, frame): + log.debug("X server has signalled a successful start.") +- x11_started[0] = True ++ x11_status.started = True + + # Fail after, let's say a minute, in case something weird happens + # and we don't receive SIGUSR1 + def sigalrm_handler(num, frame): + # Check that it didn't make it under the wire +- if x11_started[0]: ++ if x11_status.started: + return ++ x11_status.timed_out = True + log.error("Timeout trying to start %s", argv[0]) +- raise ExitError("Timeout trying to start %s" % argv[0]) + +- # preexec_fn to add the SIGUSR1 handler in the child ++ # Handle delayed start after timeout ++ def sigusr1_too_late_handler(num, frame): ++ if x11_status.timed_out: ++ log.debug("SIGUSR1 received after X server timeout. Switching back to tty1. " ++ "SIGUSR1 now again initiates test of exception reporting.") ++ signal.signal(signal.SIGUSR1, old_sigusr1_handler) ++ ++ # preexec_fn to add the SIGUSR1 handler in the child we are starting ++ # see man page XServer(1), section "signals" + def sigusr1_preexec(): + signal.signal(signal.SIGUSR1, signal.SIG_IGN) + + try: +- old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_handler) ++ old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_success_handler) + old_sigalrm_handler = signal.signal(signal.SIGALRM, sigalrm_handler) + + # Start the timer +@@ -249,16 +270,31 @@ def startX(argv, output_redirect=None, timeout=X_TIMEOUT): + preexec_fn=sigusr1_preexec) + WatchProcesses.watch_process(childproc, argv[0]) + +- # Wait for SIGUSR1 +- while not x11_started[0]: ++ # Wait for SIGUSR1 or SIGALRM ++ while x11_status.needs_waiting(): + signal.pause() + + finally: +- # Put everything back where it was ++ # Stop the timer + signal.alarm(0) +- signal.signal(signal.SIGUSR1, old_sigusr1_handler) + signal.signal(signal.SIGALRM, old_sigalrm_handler) + ++ # Handle outcome of X start attempt ++ if x11_status.started: ++ signal.signal(signal.SIGUSR1, old_sigusr1_handler) ++ elif x11_status.timed_out: ++ signal.signal(signal.SIGUSR1, sigusr1_too_late_handler) ++ # Kill Xorg because from now on we will not use it. It will exit only after sending ++ # the signal, but at least we don't have to track that. ++ WatchProcesses.unwatch_process(childproc) ++ childproc.terminate() ++ log.debug("Exception handler test suspended to prevent accidental activation by " ++ "delayed Xorg start. Next SIGUSR1 will be handled as delayed Xorg start.") ++ # Raise an exception to notify the caller that things went wrong. This affects ++ # particularly pyanaconda.display.do_startup_x11_actions(), where the window manager ++ # is started immediately after this. The WM would just wait forever. ++ raise TimeoutError("Timeout trying to start %s" % argv[0]) ++ + + def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_output=True, + binary_output=False, filter_stderr=False): +diff --git a/pyanaconda/display.py b/pyanaconda/display.py +index 8379d9c..b577eb8 100644 +--- a/pyanaconda/display.py ++++ b/pyanaconda/display.py +@@ -22,6 +22,7 @@ + import os + import subprocess + import time ++import textwrap + import pkgutil + + from pyanaconda.core.configuration.anaconda import conf +@@ -49,6 +50,14 @@ from pyanaconda.anaconda_loggers import get_module_logger, get_stdout_logger + log = get_module_logger(__name__) + stdout_log = get_stdout_logger() + ++X_TIMEOUT_ADVICE = \ ++ "Do not load the stage2 image over a slow network link.\n" \ ++ "Wait longer for the X server startup with the inst.xtimeout= boot option." \ ++ "The default is 60 seconds.\n" \ ++ "Load the stage2 image into memory with the rd.live.ram boot option to decrease access " \ ++ "time.\n" \ ++ "Enforce text mode when installing from remote media with the inst.text boot option." ++# on RHEL also: "Use the customer portal download URL in ilo/drac devices for greater speed." + + # Spice + +@@ -78,7 +87,7 @@ def ask_vnc_question(anaconda, vnc_server, message): + App.initialize() + loop = App.get_event_loop() + loop.set_quit_callback(tui_quit_callback) +- spoke = AskVNCSpoke(anaconda.ksdata, message) ++ spoke = AskVNCSpoke(anaconda.ksdata, message=message) + ScreenHandler.schedule_screen(spoke) + App.run() + +@@ -314,9 +323,23 @@ def setup_display(anaconda, options): + try: + start_x11(xtimeout) + do_startup_x11_actions() +- except (OSError, RuntimeError) as e: ++ except TimeoutError as e: + log.warning("X startup failed: %s", e) +- stdout_log.warning("X startup failed, falling back to text mode") ++ print("\nX did not start in the expected time, falling back to text mode. There are " ++ "multiple ways to avoid this issue:") ++ wrapper = textwrap.TextWrapper(initial_indent=" * ", subsequent_indent=" ", ++ width=os.get_terminal_size().columns - 3) ++ for line in X_TIMEOUT_ADVICE.split("\n"): ++ print(wrapper.fill(line)) ++ util.vtActivate(1) ++ anaconda.display_mode = constants.DisplayModes.TUI ++ anaconda.gui_startup_failed = True ++ time.sleep(2) ++ ++ except (OSError, RuntimeError) as e: ++ log.warning("X or window manager startup failed: %s", e) ++ print("\nX or window manager startup failed, falling back to text mode.") ++ util.vtActivate(1) + anaconda.display_mode = constants.DisplayModes.TUI + anaconda.gui_startup_failed = True + time.sleep(2) +-- +2.23.0 + -- Gitee