keithp@azure.UUCP (Keith Packard) (10/18/84)
I found an interesting bug in the pty controller driver. A program hanging on a read from the controlling side of a pty gets swapped out. When this program is swapped back in, it continues the wait *but* when it successfully reads from the pty, processes the data and reads again, read returns -1 instead of hanging on the read. Note that the data is being fed to this program from a sequence of other programs which write out a small amount of text to the other end of the pty and close the pty. (Actually my cd is aliased to: 'cd \!*; echo $cwd > /dev/ttypf' but the problem even occurs if the process writing to the device exits as in cp) Here is the source text for the faulty program: /* * pty.c read from pty, write to stdout. * good for fixed pipes. writes name of * pty to file specified by first argument, stdin default. */ # include <sys/file.h> # include <sgtty.h> # include <signal.h> char buffer[4096]; int named = 2; int off = 0; char pname[] = "/dev/ptypf"; char tname[] = "/dev/ttypf\n"; char devName[] = "0123456789abcdef"; main (argc, argv) char **argv; { register int fd, len, count; char nbuf[15]; if (argc == 2) { named = open (argv[1], O_WRONLY|O_TRUNC|O_CREAT, 0600); if (named == -1) { write (2, "could not access file\n", 22); _exit (1); } } else { write (2, "usage: pty file\n"); _exit (2); } fd = openPty(); if (fd < 0) _exit (1); if (fork()) _exit (0); ioctl (fd, FIONBIO, &off); close (named); close (0); close (2); for (;;) { len = read (fd, buffer, 4096); if (len > 0) { if (buffer[0] == '#') _exit(); if (write (1, buffer, len) == -1) _exit(); } else { extern int errno; printf ("len was: %d\n", len); printf ("error was: %d\n", errno); perror ("error name on write"); exit (1); } } } # define DEVINDEX 9 openPty () { register int fd; register int dev; dev = 16; do { if (dev == 0) return -1; pname [DEVINDEX] = devName [--dev]; } while ((fd = open (pname, 2)) == -1); tname [DEVINDEX] = devName [dev]; write (named, tname, sizeof (tname) - 1); return fd; } To repeat: cc -o pty pty.c pty foo > outputfile set pty=`cat foo` cp /etc/motd $pty wait until pty is swapped cp /etc/motd $pty and cat the outputfile.
terryl@tekchips.UUCP () (10/20/84)
Oops, I found out why the error was ENOTTY after the program swapped; in the original program, an error is detected and errno is printed. But errno is printed in something like the second or third printf, so all bets are off that the value printed is what really caused the error to begin with. If you save the value of errno and then print the saved value, the error is EIO even after swapping, which is what is to be expected. Terry Laskodi of Tektronix