proper recovery from EINTR

steve at anasazi.uucp steve at anasazi.uucp
Mon Dec 10 08:59:38 AEST 1984


The folks here at Anasazi have been puzzling over this one for a while.
Any pointers to a solution, or even an informed discussion, would be
appreciated.

The problem is to write two functions v_read and v_write which behave
like the UNIX system calls read and write, except that they work "properly"
on a slow device while (unrelated) signals are being caught.  Specifically,
assume that the file descriptor may denote a "slow" device such as a terminal,
and various signals may be set up to be caught, and other processes may be
doing kill's on those signals at random times.  Despite this, in cases where
read and write would return -1 with errno = EINTR, v_read and v_write are
required to transfer all n bytes correctly, in the correct order, with no
omissions or duplications, and return the number of bytes n that were
transferred (assuming no real error like EOF occurred).

Here is a first cut for v_read (v_write is similar):

	v_read(fd, buf, n)

	int fd, n;
	char *buf;

	{
		register int i;
		register char *cp;
		int serrno;

		serrno = errno;
		cp = buf;
		i = 0;
		while (i < n)
			switch (read(fd, cp, 1))
			{
			  case -1:
				if (errno != EINTR)
					return -1;
				break;
			  case 0:
				errno = serrno;
				return i;
			  case 1:
				cp++;
				i++;
				break;
			  default:
				abort();
			}
		errno = serrno;
		return n;
	}

Some obvious questions:  If you do a read system call with a length > 1,
and EINTR occurs, is there a way to find out how many bytes were actually
transferred?  Even in the length = 1 case, can you really be sure that the
one byte was not transferred?  Finally, is there a way to speed this up,
and avoid n system calls to do the read?

Thanks for any help.

Stephen E. F. Villee (decvax!noao!terak!anasazi!steve)
International Anasazi, Inc.
2219 East University Drive
Phoenix, Arizona 85034
(602) 275-0302



More information about the Comp.unix.wizards mailing list