WHAT:
	This patch fixes a bug in xterm which was there for like a decade.
 
	This patch is against xterm 156 distributed with XFree86.
	xterm home page is at http://dickey.his.com/xterm/xterm.html

PROBLEM:
	In Linux system, if you run xterm with bash (like bash 2.05) and type 
	'suspend', xterm will appear as if had hung, and will not respond to 
	keystrokes at all (just like bash itself will do). So you for example
	can't pop-up the xterm's menu's in order to send 'SIGCONT' to bash
	itself.

MORE DETAILED PROBLEM:
	What is happening is that bash it sending itself SIGSTOP, and it is
	being stopped. Per speficication it also menas that OS is sending 
	SIGCHLD to parent of the bash (XTERM).

	Now the issue is that xterm assumes it can't happen and it expects
	to receive SIGHCHLD only upon *termination* of its chilren. So there
	happens a Catch-22 situation with xterm waitng for child to die,
	and child waiting for SIGCONT.

DETAILS:

	Now interestingly enough xterm appears to work on Solaris, while it 
	does not work (as described above) on Linux. Checking signal(3C) man 
	page on Solaris we come across this qutoe:

     "
     If signal() or sigset() is used to set   SIGCHLD's  disposi-
     tion  to a signal handler, SIGCHLD will not be sent when the
     calling process's children are stopped or continued.
     "

	So it makes it "linux only" problem.

	The two key lines in xterm sources relevant here are :

	xterm-156/main.c:1370:main()
 
	       signal (SIGCHLD, reapchild);

        xterm-156/main.c:3240:reapchild()

		pid = wait(NULL);
	
	note that there's also "signal (SIGCHLD, SIG_DFL);" in spawn()
	part of main.c file, but it is not relevant here.

SOLUTIONS:

	Above suggest two possible solutions:

	a)
	replace wait() call with waitpid(), and make sure to pass WUNTRACED
	option so that it also returns for children. 

	This modification would also require to add further logic to test 
	why waitpid() has returned.

	b)
	replace signal() call with sigaction() and make usre it uses 
	SA_NOCLDSTOP option. In this whay signal handler won't get called 
	on SIGSTOP.
	
	This modification seems to be more transparent, as just changes 
	one (3-4) line(s) of code in main() to add a wrapper. This is the 
	way I decided to do this.

OTHER:
	Thanks to xterm maintainer, Thomas E. Dickey, for providing 
	insights on xterm debugging.

	The example code is based on sample code from Richard Steven's 
	"Advaned Programming In the Unix Environment", ch 10.14.

        Adam Sulmicki <adam@cfar.umd.edu>
	Tue May 22 08:30:04 EDT 2001
        http://www.eax.com/patches/

-------------------------------------------------------------------------------
--- xterm-156/main.c-old	Sat Apr 28 09:51:55 2001
+++ xterm-156/main.c	Tue May 22 09:25:54 2001
@@ -1298,6 +1298,27 @@
 	return code;
 }
 
+#if defined(linux) && defined(_POSIX_SOURCE)
+
+typedef void (*sigfunc)(int);
+
+/* make sure we sure we ignore SIGCHILD for the cases parent 
+   has just been stoppend and not actually killed */
+
+sigfunc posix_signal(int signo, sigfunc func ) {
+
+	struct sigaction act, oact;
+
+	act.sa_handler = func;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = SA_NOCLDSTOP|SA_RESTART;
+	if (sigaction(signo, &act, &oact) < 0)
+		return(SIG_ERR);
+	return (oact.sa_handler);
+}
+
+#endif /* linux && _POSIX_SOURCE */
+
 int
 main (int argc, char *argv[])
 {
@@ -1890,8 +1911,12 @@
 
 #ifndef VMS
 	/* Child process is out there, let's catch its termination */
-	(void) signal (SIGCHLD, reapchild);
 
+#if defined(linux) && defined(_POSIX_SOURCE)
+	posix_signal(SIGCHLD,reapchild);
+#else
+	(void) signal (SIGCHLD, reapchild);
+#endif
 	/* Realize procs have now been executed */
 
 #ifndef AMOEBA

