[PATCH] ash: clear NONBLOCK flag from stdin when in foreground

Rich Felker dalias at aerifal.cx
Thu Aug 18 00:10:23 UTC 2011


On Thu, Aug 18, 2011 at 01:11:37AM +0200, Denys Vlasenko wrote:
> > you simply 
> > call poll first (or select, but select requires the fd # to be < 1024)
> > to check that it won't block, then call read. select and poll are
> > specified to only mark the fd readable if a read would not block.
> 
> An example from a different area of Unix API:
> 
> EINTR is supposed to be returned only if non-DFL,
> non-IGN signal was reseived and handler was executed.
> Right? Right... but...
> real world chimes in: EINTR also may be returned if someone
> happened to attach to your program with "strace -p PID"
> while you are in a syscall. Syscall may return EINTR even though
> *no signal whatsoever* was delivered.

This is only true for non-restartable syscalls like sleep. open, read,
write, etc. can never return EINTR unless interrupted by a
non-restarting signal handler.

> My question stands:
> 
> "How can I do nonblocking read from fd 0 without
> affecting other processes which might share it?"

Something like this (untested and missing some error handling):

static void *reader(void *x)
{
	char buf[BUFSIZ];
	int *fds = x, rd = fds[0], wr = fds[1];
	free(x);
	for (;;) {
		ssize_t i, k, l = read(rd, buf, sizeof buf);
		for (i=0; i<l; i+=k) {
			k = write(wr, buf+i, l-i);
			if (k<0) break;
		}
		if (l<=0 || k<0) break;
	}
	close(wr);
	return 0;
}

int newfd, *p=malloc(sizeof *p * 2)
pipe(p);
newfd = p[0];
p[0] = oldfd;
pthread_create(&td, 0, reader, p);

Now poll and read from newfd...

> > If other processes might attempt a read at the same time your process
> > does, then you have serious data races which are probably not solvable
> > anyway.
> 
> Well, the data units might be single bytes.

Indeed this is one of the few valid uses...

Rich


More information about the busybox mailing list