[comp.windows.x] Unofficial Xdm Patches

tsk@MN.ECN.PURDUE.EDU (Timothy S Kechkaylo) (09/18/89)

	We have some NCD X terminals here at Mechanical Engineering
at Purdue and whenever anyone turns off/on/resets the terminal, the xdm
prompt doesn't come back.  So, I've made some changes to xdm to keep the
xdm message up on the display and to kill off any child procs from the
X session when the X terminal gets turned off/on/reset.  It seems to
work rather well.  The included patches to xdm are UNOFFICIAL and are
not standard or approved patches.

	The xdm session manager checks the pulse of the X terminal every
checkPulse interval.  If the X terminal is off, the call blocks until
the X terminal comes back up (or times out) and then gets a "connection
reset by peer" and then does the resetting.  If the X terminal has been
reset since the last pulse checkup, then the error "connection reset by
peer" comes back right away and the resetting then takes place.  So the
worst case situation where the terminal would unusable would be:

	pulse_check_interval - x_term_reboot_time + xdm_response_new_prompt

For us it's about:

	60 sec - 16 sec + 5 sec = 49 secs worst case

The 16 sec reboot time was quite fast, an idle net and booting from
an idle sun 4/280.

The parameters are set in the xdm resources and default to:

	checkPulse: false
	pulseInterval: 60 secs

The included patches make changes to:

	dm.h resources.c session.c

Oh, by the way, the pulse checking is implemented using
XNoOp and then a Xsync Xlib call.

Everything in the patches are ifdef'd PULSE, so you should be
aware of this special define.

----------
Timothy S. Kechkaylo		UUCP: ...{rutgers|ucbvax|decvax}!pur-ee!tsk
Systems Analyst			ARPA: tsk@ecn.purdue.edu
Mechanical Engineering		BITNET: tsk%ee.ecn.purdue.edu@PURCCVM
Purdue University		PHONE: (317) 494-5988
West Lafayette, IN 47907	FAX:   (317) 494-0539


-----------CUT----------HERE--------------
*** /tmp/,RCSt1a17595	Sun Sep 17 18:20:07 1989
--- dm.h	Wed Aug 30 09:21:05 1989
***************
*** 107,112
  	int		openDelay;	/* open delay time */
  	int		openRepeat;	/* open attempts to make */
  	int		openTimeout;	/* abort open attempt timeout */
  	int		terminateServer;/* restart for each session */
  	int		grabTimeout;	/* time to wait for grab */
  	DisplayType	displayType;	/* method to handle with */

--- 107,116 -----
  	int		openDelay;	/* open delay time */
  	int		openRepeat;	/* open attempts to make */
  	int		openTimeout;	/* abort open attempt timeout */
+ #ifdef PULSE
+ 	int		pulseInterval;	/* check server's pulse interval */
+ 	int		checkPulse;	/* check server's pulse */
+ #endif
  	int		terminateServer;/* restart for each session */
  	int		grabTimeout;	/* time to wait for grab */
  	DisplayType	displayType;	/* method to handle with */
*** /tmp/,RCSt1a17600	Sun Sep 17 18:20:08 1989
--- resource.c	Wed Aug 30 09:21:05 1989
***************
*** 120,125
  				"5",
  "openTimeout",	"OpenTimeout",	DM_INT,		boffset(openTimeout),
  				"30",
  "terminateServer","TerminateServer",DM_BOOL,	boffset(terminateServer),
  				"false",
  "userPath",	"Path",		DM_STRING,	boffset(userPath),

--- 120,131 -----
  				"5",
  "openTimeout",	"OpenTimeout",	DM_INT,		boffset(openTimeout),
  				"30",
+ #ifdef PULSE
+ "pulseInterval","PulseInterval",DM_INT,		boffset(pulseInterval),
+ 				"60",
+ "checkPulse",	"CheckPulse",	DM_BOOL,	boffset(checkPulse),
+ 				"false",
+ #endif
  "terminateServer","TerminateServer",DM_BOOL,	boffset(terminateServer),
  				"false",
  "userPath",	"Path",		DM_STRING,	boffset(userPath),
*** /tmp/,RCSt1a17605	Sun Sep 17 18:20:09 1989
--- session.c	Sun Sep 17 18:19:20 1989
***************
*** 30,35
  
  static int	clientPid;
  
  ManageSession (d)
  struct display	*d;
  {

--- 30,107 -----
  
  static int	clientPid;
  
+ #ifdef PULSE
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ 
+ static struct display *pulse_d;
+ static Display *pulse_dpy;
+ 
+ static
+ noPulse ()
+ {
+ 	/*
+ 	 * Cannot get here without and error of some kind
+ 	 */
+ 	if ( errno < sys_nerr )
+ 		Debug ("WARNING: noPulse: %s\n", sys_errlist[errno]);
+ 	else
+ 		Debug ("WARNING: noPulse: unknown error number\n");
+ 
+ 	/*
+ 	 * Kill process group and exit like nothing happened
+ 	 */
+ 	if ( killpg (clientPid, SIGTERM) == -1 ) {
+ 		if ( errno < sys_nerr )
+ 			LogError ("WARNING: killpg: %s\n", sys_errlist[errno]);
+ 		else
+ 			LogError ("WARNING: killpg: unknown error\n");
+ 	}
+ 	else
+ 		Debug ("NOTICE: noPulse: killed process group\n");
+ 
+ 	SessionExit (OBEYTERM_DISPLAY);
+ }
+ 
+ static
+ checkPulse ()
+ {
+ 	Debug ("NOTICE: Checking pulse\n");
+ 	XNoOp(pulse_dpy);
+ 	XSync(pulse_dpy);
+ 	Debug ("NOTICE: Is alive\n");
+ 	alarm (pulse_d->pulseInterval);
+ }
+ 
+ static
+ PulseOn (d, dpy)
+ struct display	*d;
+ Display *dpy;
+ {
+ 	pulse_d = d;		/* tnx davey */
+ 	pulse_dpy = dpy;
+ 
+ 	if ( d->checkPulse ) {
+ 		XSetIOErrorHandler (noPulse);
+ 		signal (SIGALRM, checkPulse);
+ 		alarm (pulse_d->pulseInterval);
+ 		Debug ("NOTICE: Pulse checking enabled\n");
+ 	}
+ }
+ 
+ static
+ PulseOff ()
+ {
+ 	if ( pulse_d->checkPulse ) {
+ 		alarm (0);
+ 		signal (SIGALRM, SIG_DFL);
+ 		XSetIOErrorHandler (NULL);
+ 		Debug ("NOTICE: Pulse checking turned off\n");
+ 	}
+ }
+ #endif
+ 
  ManageSession (d)
  struct display	*d;
  {
***************
*** 44,49
  	 */
  	LoadXloginResources (d);
  	dpy = InitGreet (d);
  	for (;;) {
  		/*
  		 * Step 6: Greet user, requesting name/password

--- 116,124 -----
  	 */
  	LoadXloginResources (d);
  	dpy = InitGreet (d);
+ #ifdef PULSE
+ 	PulseOn (d, dpy);
+ #endif
  	for (;;) {
  		/*
  		 * Step 6: Greet user, requesting name/password
***************
*** 58,63
  			FailedLogin (d, &greet);
  	}
  	DeleteXloginResources (d, dpy);
  	CloseGreet (d);
  	Debug ("Greet loop finished\n");
  	/*

--- 133,141 -----
  			FailedLogin (d, &greet);
  	}
  	DeleteXloginResources (d, dpy);
+ #ifdef PULSE
+ 	PulseOff ();
+ #endif
  	CloseGreet (d);
  	Debug ("Greet loop finished\n");
  
***************
*** 60,65
  	DeleteXloginResources (d, dpy);
  	CloseGreet (d);
  	Debug ("Greet loop finished\n");
  	/*
  	 * Step 8: Run system-wide initialization file
  	 */

--- 138,148 -----
  #endif
  	CloseGreet (d);
  	Debug ("Greet loop finished\n");
+ 
+ #ifdef PULSE
+ 	dpy = XOpenDisplay (d->name);
+ 	PulseOn (d, dpy);
+ #endif
  	/*
  	 * Step 8: Run system-wide initialization file
  	 */
***************
*** 82,87
  	} else {
  		LogError ("session start failed\n");
  	}
  	/*
  	 * Step 15: run system-wide reset file
  	 */

--- 165,175 -----
  	} else {
  		LogError ("session start failed\n");
  	}
+ #ifdef PULSE
+ 	PulseOff ();
+ 	XCloseDisplay (dpy);
+ #endif
+ 
  	/*
  	 * Step 15: run system-wide reset file
  	 */
*** /tmp/,RCSt1a17610	Sun Sep 17 18:20:10 1989
--- xdm.man	Sun Sep 17 17:55:39 1989
***************
*** 209,214
  this behaviour may seem arbitrary, it has been empirically developed and
  works quite well on most systems.  The default values are
  5 for \fBopenDelay\fP, 5 for \fBopenRepeat\fP and 30 for \fBopenTimeout\fP.
  .IP "\fBDisplayManager.DISPLAY.grabTimeout\fP"
  To eliminate obvious security shortcomings in the X protocol,
  .I xdm

--- 209,225 -----
  this behaviour may seem arbitrary, it has been empirically developed and
  works quite well on most systems.  The default values are
  5 for \fBopenDelay\fP, 5 for \fBopenRepeat\fP and 30 for \fBopenTimeout\fP.
+ .IP "\fBDisplayManager.DISPLAY.checkPulse\fP"
+ .IP "\fBDisplayManager.DISPLAY.pulseInterval\fP"
+ These two variables are mainly used with X terminals and to deal with their
+ transitory behavior.  A pulse is taken of the X terminal every
+ \fBpulseInterval\fP seconds and checked to see if it is alive.
+ If it had died, then the xdm display will be redisplayed and the
+ process group associated with the user's session will recieve a SIGTERM
+ signal.  The boolean \fBcheckPulse\fP will enable or disable this checking of
+ the pulse.   The integer \fBpulseInterval\fP will set the frequency of
+ the pulse checking.  The default is, no pulse checking and an interval time
+ of 60 seconds.
  .IP "\fBDisplayManager.DISPLAY.grabTimeout\fP"
  To eliminate obvious security shortcomings in the X protocol,
  .I xdm

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (09/18/89)

    We have some NCD X terminals here at Mechanical Engineering
    at Purdue and whenever anyone turns off/on/resets the terminal, the xdm
    prompt doesn't come back.

Just so it's clear, the X Display Manager Control Protocol (XDMCP), recently
put our for Public Review, is designed to solve this problem.  NCD and others
are working on implementations.