bug in 4.2 ptys stuff. Weird results when programs are swapped.

Keith Packard keithp at azure.UUCP
Fri Oct 19 06:35:31 AEST 1984


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.



More information about the Comp.bugs.4bsd.ucb-fixes mailing list