Submitted By: Alexander E. Patrakov
Date: 2004-11-03
Initial Package Version: 6.8.1
Origin: Alexander E. Patrakov
Upstream Status: Accepted into xterm, http://bugs.xfree86.org/show_bug.cgi?id=1093
Description: prevents the race condition and deadlock in luit. Should
apply both to XOrg and XFree86.
Testcase:

(preferrably in Xnest - this will open 100 xterm windows)

for a in `seq 1 100` ; do
	( xterm -lc -e info & ) ; sleep 0.2
done

Half of xterms will be blank without this patch.

"killall luit" to close all xterms.

--- xc/programs/luit/luit.c	2004-09-21 08:05:44.000000000 +0600
+++ xc/programs/luit/luit.c.fixed	2004-10-27 12:46:24.092624776 +0600
@@ -434,6 +434,16 @@
     return 0;
 }
         
+static void
+sigwinchHandler(int sig) {
+    sigwinch_queued = 1;
+}
+
+static void
+sigchldHandler(int sig)
+{
+    sigchld_queued = 1;
+}
 
 static int
 condom(int argc, char **argv)
@@ -444,6 +454,7 @@
     char *path;
     char **child_argv;
     int rc;
+    int val;
 
     rc = parseArgs(argc, argv, child_argv0,
                    &path, &child_argv);
@@ -461,6 +472,29 @@
         perror("Couldn't drop priviledges");
         exit(1);
     }
+#ifdef SIGWINCH
+    installHandler(SIGWINCH, sigwinchHandler);
+#endif
+    installHandler(SIGCHLD, sigchldHandler);
+
+    rc = copyTermios(0, pty);
+    if(rc < 0)
+        FatalError("Couldn't copy terminal settings\n");
+
+    rc = setRawTermios();
+    if(rc < 0)
+        FatalError("Couldn't set terminal to raw\n");
+
+    val = fcntl(0, F_GETFL, 0);
+    if(val >= 0) {
+        fcntl(0, F_SETFL, val | O_NONBLOCK);
+    }
+    val = fcntl(pty, F_GETFL, 0);
+    if(val >= 0) {
+        fcntl(pty, F_SETFL, val | O_NONBLOCK);
+    }
+
+    setWindowSize(0, pty);
 
     pid = fork();
     if(pid < 0) {
@@ -470,6 +504,10 @@
 
     if(pid == 0) {
         close(pty);
+#ifdef SIGWINCH
+        installHandler(SIGWINCH, SIG_DFL);
+#endif
+        installHandler(SIGCHLD, SIG_DFL);
         child(line, path, child_argv);
     } else {
         free(child_argv);
@@ -490,6 +528,7 @@
     close(0);
     close(1);
     close(2);
+    
     pgrp = setsid();
     if(pgrp < 0) {
         kill(getppid(), SIGABRT);
@@ -517,53 +556,17 @@
     exit(1);
 }
 
-static void
-sigwinchHandler(int sig) {
-    sigwinch_queued = 1;
-}
-
-static void
-sigchldHandler(int sig)
-{
-    sigchld_queued = 1;
-}
-
 void
 parent(int pid, int pty)
 {
     unsigned char buf[BUFFER_SIZE];
     int i;
-    int val;
     int rc;
 
     if(verbose) {
         reportIso2022(outputState);
     }
 
-#ifdef SIGWINCH
-    installHandler(SIGWINCH, sigwinchHandler);
-#endif
-    installHandler(SIGCHLD, sigchldHandler);
-
-    rc = copyTermios(0, pty);
-    if(rc < 0)
-        FatalError("Couldn't copy terminal settings\n");
-
-    rc = setRawTermios();
-    if(rc < 0)
-        FatalError("Couldn't set terminal to raw\n");
-
-    val = fcntl(0, F_GETFL, 0);
-    if(val >= 0) {
-        fcntl(0, F_SETFL, val | O_NONBLOCK);
-    }
-    val = fcntl(pty, F_GETFL, 0);
-    if(val >= 0) {
-        fcntl(pty, F_SETFL, val | O_NONBLOCK);
-    }
-
-    setWindowSize(0, pty);
-
     for(;;) {
         rc = waitForInput(0, pty);
 
