/*---------------------------------------------------------------------- | Stevens says the following (p.400): | | If we encounter the enf of file on a descriptor, that descriptor | is considered readable by select. We then call read and it returns 0, | the normal Unix way to signify end of file. (Many people incorrectly | assume select indicates an exception condition on a descriptor | when the end of file is reached | | This program serves to verify this statement. It creates a child | process that writes "hello world" over a pipe to the parent, | then sleeps for 2 seconds, and then exits. | | The parent reads the "hello world" message, and then tries reading | further. However, if you execute the code, you'll see that | the second read() attempt returns a value of 0 (since the child's | end of the pipe is closed) | | Author: Justin Gamble, Nov 21/99 ----------------------------------------------------------------------*/ #include #include /* memset() */ #include /* fd_set data type */ #include /* struct timeval */ #include /* function prototype might be here */ #include #define MAXLINE 80 int main(int argc, char *argv[]) { char buf[MAXLINE]; /* stores messages received over pipe */ fd_set readSet; /* used in parent' select() call */ int numReady = 0; /* # of FDs ready on parent's call to select() */ int fd[2]; /* used for pipe between child & parent */ int maxFd1 = 2; /* stdin, stdout, stderr are already open */ int readReturn = 0; /* stores return value of parent's read() */ /* * change the default stdout buffering: don't use any buffering */ if (setvbuf(stdout, NULL, _IONBF, NULL) != 0) { fprintf(stderr, "setvbuf error\n"); exit(1); } /* * set up pipe */ if (pipe(fd) < 0) { printf("pipe error\n"); exit(1); } /* * update maxFd1 */ maxFd1 = fd[0]; if (fd[1] > maxFd1) maxFd1 = fd[1]; printf("maxFd1 is [%d]\n", maxFd1); /* * generate SIGPIPE */ switch ( fork() ) { case -1: /* error */ printf("fork error\n"); exit(1); case 0 : /* child */ close(fd[0]); write(fd[1], "hello world", 11); printf("CHILD: going to sleep for 2 seconds\n"); sleep(2); printf("CHILD: exiting\n"); exit(1); default: /* parent */ close(fd[1]); readReturn = read(fd[0], &buf, 11); assert(readReturn == 11); buf[11] = '\0'; printf("PARENT: received [%s]\n", buf); printf("PARENT: waiting on select()\n"); FD_ZERO(&readSet); FD_SET(fd[0], &readSet); numReady = select(maxFd1+1, &readSet, NULL, NULL, NULL); printf("PARENT: select says [%d] FDs are ready for reading\n", numReady); assert(FD_ISSET(fd[0], &readSet)); /* only fd in set */ readReturn = read(fd[0], &buf, 11); printf("PARENT: return value of read() is [%d]\n", readReturn); } }