[net.bugs.4bsd] bug in 4.2 ptys stuff. Weird results when programs are swapped.

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