[net.emacs] Time/Load bug in Gosling

rosen@gypsy.UUCP (03/11/86)

We are using Gosling Emacs-#264 running on a VAX 780 with 4.2BSD.  Most of
us who use Emacs also use the 'time.ml' package to display the system time
and load at the bottom of the screen.

In doing this we have noted a very strange feature which is not bothersome,
but I would like to know why it happens.  What happends is that just after the
machine crashes or is shut down and is then brought back up, it will not
display the time and load, but rather it will just say:

		(time and load)

For about 12-24 hours it is this way and eventually it just returns to
something like this:

		(12:30pm  3.40[4])

I realize that this may be an esoteric question, but I was wondering what's
going on here.  Anybody have any ideas?

----------------
| Steve Rosen
| Siemens Research and Technology Laboratories
| Princeton, NJ

USENET:    adrvax\
            ihnp4 |
        princeton |-->!siemens!gypsy!rosen
            topaz |
           vrdxhq/

ARPA:   siemens!gypsy!rosen@TOPAZ

hansen@mips.UUCP (Craig Hansen) (03/13/86)

> We are using Gosling Emacs-#264 running on a VAX 780 with 4.2BSD.  Most of
> us who use Emacs also use the 'time.ml' package to display the system time
> and load at the bottom of the screen.
> 
> In doing this we have noted a very strange feature which is not bothersome,
> but I would like to know why it happens.  What happends is that just after the
> machine crashes or is shut down and is then brought back up, it will not
> display the time and load, but rather it will just say:
> 
> 		(time and load)

I've noticed a similar problem here, but for me it's more serious.
It appears that the sub-process facility, which uses 4.2 sockets,
does not properly initialize some aspect of the "psuedo-terminal"
used in the connection.  When this happens, time.ml never updates
the "time and load" display, but also crashes unmercifully if
you try to restart time.ml, or any other sub-process (such as
when using the "compile" or "shell" packages).  I can make the
problem go away by starting a bunch of rlogin's (!) which eventually
reach the pty which causes the problems.  I've noticed that after
doing that, compile or shell processes which are started thereafter
seem to place an extra ^M at the end of each line, indicating
some misfortune with the "nl" setting on the pty.

Sigh.  Who's got the fortitude to track this junk down anymore?

Craig Hansen
MIPS Computer Systems
...decwrl!glacier!mips

bobr@zeus.UUCP (Robert Reed) (03/14/86)

In article <397@mips.UUCP> hansen@mips.UUCP (Craig Hansen) writes:
>> We are using Gosling Emacs-#264 running on a VAX 780 with 4.2BSD.  Most of
>> us who use Emacs also use the 'time.ml' package to display the system time
>> and load at the bottom of the screen.
>> 
>> In doing this we have noted a very strange feature which is not bothersome,
>> but I would like to know why it happens.  What happends is that just after the
>> machine crashes or is shut down and is then brought back up, it will not
>> display the time and load, but rather it will just say:
>> 
>> 		(time and load)
>
>I've noticed a similar problem here, but for me it's more serious...

The problem is that Emacs 264, when it opens a pty, only tries to open
the master, not looking at whether the slave side is accessible.  After a
crash, the access rights of pty slaves can be left in various wierd states.
Emacs tries to open the master side, succeeds, forks the process which opens
the slave side but can't write to it.  Time.ml initially sets the global
mode string to (time and load), but no data comes throught the pty so it
never gets updated.

The solution is to verify that BOTH the master can be opened AND that the
slave is writeable before accepting a pty/tty pair.  The appropriate routine
(with thanks for previous help from Chris Torek) is:

static char *
pty(ptyv)
    int    *ptyv;

/* Find a free pty and open it.  Return the name of the slave side and stuff
 * the file descriptor in the supplied pointer.  N.B.: we make the following
 * assumptions:
 *        1. Pty masters are /dev/pty[pqr...][0-9a-f].
 *        2. Pty slave names are the same as the master but with a 't' in
 *           place of the first 'p'.
 *        3. Ptys stop as soon as a "stat" call fails on the master name (names
 *           are tried in alphabetical order).  (Actually, we cheat and stat
 *           only the first of each set of 16.)
 * A return value of 0 indicates no free ptys.
 */
{
    static char name[24];
    register int    fd;
    register char  *p = name;
    struct stat stb;

    /* init <name> to a generic pty name with *p the last character of the
     * name
     */
    {
        register char    *s = "/dev/ptyp";
        while (*p++ = *s++)
            ;
        *p-- = 0;
    }

    /* for each block of ptys, try to open the master; if that works, make
     * sure the slave is accessible, then return the name of the slave
     */
    for (;;) {
        register int    i;
        *p = '0';
        if (stat(name, &stb) < 0)
            return (0);
        for (i = 0; i < 16; ) {

            /* If the master pty can be opened and its slave is accessible
             * then set nonblocking IO and return the name of the
             * corresponding tty
             */
            if ((fd = open(name, 2)) >= 0) {
                p[-4] = 't';
                if (access (name, 6) == 0) {
                    int        on = 1;
                    (void) ioctl(fd, FIONBIO, &on);
                    *ptyv = fd;
                    return (name);
                }
                p[-4] = 'p';
                (void) close(fd);
            }
            *p = "123456789abcdef"[i++];
        }
        p[-1]++;
    }
}