[PATCH 09/22] Move the X startup logic to iutil

David Shea dshea at redhat.com
Wed Jun 3 16:03:33 UTC 2015


Move all the parts that set up signal handlers and wait for SIGUSR1 to
iutil.startX. Use startX for starting Xvnc since it does the same thing
as Xorg.

(cherry picked from commit dce67490ea5cac2c9f3c5e080b76ad355d6ded25)

Related: rhbz#1188287
---
 anaconda            | 56 +++++++++--------------------------------------------
 pyanaconda/iutil.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 pyanaconda/vnc.py   | 12 ++----------
 3 files changed, 63 insertions(+), 57 deletions(-)

diff --git a/anaconda b/anaconda
index 03e250e..e414d6f 100755
--- a/anaconda
+++ b/anaconda
@@ -110,55 +110,17 @@ def startSpiceVDAgent():
         log.info("Started spice-vdagent.")
 
 def startX11():
-    # Start X11 with its USR1 handler set to ignore, which will make it send
-    # us SIGUSR1 if it succeeds. If it fails, catch SIGCHLD and bomb out.
-    # Use a list so the value can be modified from the handler
-    x11_started = [False]
-    def sigusr1_handler(num, frame):
-        log.debug("X server has signalled a successful start.")
-        x11_started[0] = True
+    # Open /dev/tty5 for stdout and stderr redirects
+    xfd = open("/dev/tty5", "a")
 
-    # 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]:
-            return
-        log.error("Timeout trying to start the X server")
-        raise iutil.ExitError("Timeout trying to start the X server")
+    # Start Xorg and wait for it become ready
+    iutil.startX(["Xorg", "-br", "-logfile", "/tmp/X.log",
+                  ":1", "vt6", "-s", "1440", "-ac",
+                  "-nolisten", "tcp", "-dpi", "96",
+                  "-noreset"], output_redirect=xfd)
 
-    # preexec_fn to add the SIGUSR1 handler in the child
-    def sigusr1_preexec():
-        signal.signal(signal.SIGUSR1, signal.SIG_IGN)
-
-    try:
-        old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_handler)
-        old_sigalrm_handler = signal.signal(signal.SIGALRM, sigalrm_handler)
-
-        # Open /dev/tty5 for stdout and stderr redirects
-        xfd = open("/dev/tty5", "a")
-
-        # Start the timer
-        signal.alarm(60)
-
-        childproc = iutil.startProgram(["Xorg", "-br", "-logfile", "/tmp/X.log",
-                                        ":1", "vt6", "-s", "1440", "-ac",
-                                        "-nolisten", "tcp", "-dpi", "96",
-                                        "-noreset"], stdout=xfd, stderr=xfd,
-                                        preexec_fn=sigusr1_preexec)
-        iutil.watchProcess(childproc, "Xorg")
-
-        # Wait for SIGUSR1
-        while not x11_started[0]:
-            signal.pause()
-
-        # Now that X is started, make $DISPLAY available
-        os.environ["DISPLAY"] = ":1"
-    finally:
-        # Put everything back where it was
-        signal.alarm(0)
-        signal.signal(signal.SIGUSR1, old_sigusr1_handler)
-        signal.signal(signal.SIGALRM, old_sigalrm_handler)
+    # Now that X is started, make $DISPLAY available
+    os.environ["DISPLAY"] = ":1"
 
 # function to handle X startup special issues for anaconda
 def doStartupX11Actions():
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 12ec308..d384696 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -160,6 +160,58 @@ def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subp
                             close_fds=True,
                             preexec_fn=preexec, cwd=root, env=env, **kwargs)
 
+def startX(argv, output_redirect=None):
+    """ Start X and return once X is ready to accept connections.
+
+        X11, if SIGUSR1 is set to SIG_IGN, will send SIGUSR1 to the parent
+        process once it is ready to accept client connections. This method
+        sets that up and waits for the signal or bombs out if nothing happens
+        for a minute. The process will also be added to the list of watched
+        processes.
+
+        :param argv: The command line to run, as a list
+        :param output_redirect: file or file descriptor to redirect stdout and stderr to
+    """
+    # Use a list so the value can be modified from the handler function
+    x11_started = [False]
+    def sigusr1_handler(num, frame):
+        log.debug("X server has signalled a successful start.")
+        x11_started[0] = 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]:
+            return
+        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
+    def sigusr1_preexec():
+        signal.signal(signal.SIGUSR1, signal.SIG_IGN)
+
+    try:
+        old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_handler)
+        old_sigalrm_handler = signal.signal(signal.SIGALRM, sigalrm_handler)
+
+        # Start the timer
+        signal.alarm(60)
+
+        childproc = startProgram(argv, stdout=output_redirect, stderr=output_redirect,
+                preexec_fn=sigusr1_preexec)
+        watchProcess(childproc, argv[0])
+
+        # Wait for SIGUSR1
+        while not x11_started[0]:
+            signal.pause()
+
+    finally:
+        # Put everything back where it was
+        signal.alarm(0)
+        signal.signal(signal.SIGUSR1, old_sigusr1_handler)
+        signal.signal(signal.SIGALRM, old_sigalrm_handler)
+
 def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_output=True,
         binary_output=False, filter_stderr=False):
     """ Run an external program, log the output and return it to the caller
diff --git a/pyanaconda/vnc.py b/pyanaconda/vnc.py
index 62f26c2..70800ad 100644
--- a/pyanaconda/vnc.py
+++ b/pyanaconda/vnc.py
@@ -223,21 +223,13 @@ class VncServer:
                         "SecurityTypes=%s" % SecurityTypes, "rfbauth=%s" % rfbauth ]
 
         try:
-            xvncp = subprocess.Popen(xvnccommand, stdout=self.openlogfile(), stderr=subprocess.STDOUT)
+            iutil.startX(xvnccommand, output_redirect=self.openlogfile())
         except OSError:
             stdoutLog.critical("Could not start the VNC server.  Aborting.")
             iutil.ipmi_report(constants.IPMI_ABORTED)
             sys.exit(1)
 
-        # Lets give the xvnc time to initialize
-        time.sleep(1)
-
-        # Make sure it hasn't blown up
-        if xvncp.poll() != None:
-            iutil.ipmi_report(constants.IPMI_ABORTED)
-            sys.exit(1)
-        else:
-            self.log.info(_("The VNC server is now running."))
+        self.log.info(_("The VNC server is now running."))
 
         # Lets tell the user what we are going to do.
         if self.vncconnecthost != "":
-- 
2.1.0



More information about the anaconda-patches mailing list