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.