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 xdmrws@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.