Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!zaphod.mps.ohio-state.edu!sdd.hp.com!news.cs.indiana.edu!nstn.ns.ca!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!mouse From: mouse@thunder.mcrcim.mcgill.edu (der Mouse) Newsgroups: comp.unix.questions Subject: Re: How do I recover my pipe on my Parent's Death? Message-ID: <1991May24.112734.4314@thunder.mcrcim.mcgill.edu> Date: 24 May 91 11:27:34 GMT References: <1991May21.213431.2193@odetics.com> Distribution: na Organization: McGill Research Centre for Intelligent Machines Lines: 101 In article <1991May21.213431.2193@odetics.com>, frank@odetics.com (Frank Merrow) writes: > I am attempting to monitor a number of file descriptors for input > using select(). Below I have included a piece of my code. Actually > things work pretty good, EXCEPT for some reason when one of the > processes (my parent in this case) dies. > At any rate once the parent dies, select() immediately releases, but > the ioctl() shows "nothing" in the pipe so I go back to the select() > which immediately releases and so on. What do I need to do to > detect/clear the condition. (Questions generally end with `?', not `.'.) select() for input returns when a read() call will not block. This is not always the same as returning when there is something to read. In your case, you've reached EOF on the pipe; if you call read() you'll see that it returns 0. Naturally FIONREAD returns 0, because there's nothing there. As for detecting it, you already have: select() indicates that it's ready for input, but there's nothing there. To clear it, you can't; that pipe is forever going to show EOF. You can't do much with it but close it. > for (keep_going=TRUE;keep_going;) > { > if (select(numfds,&readfds,NULL,NULL,NULL) < 1) > fatal("select() error in main(xfs)"); > PRINT_TRACE("select() released"); > for (i=0;i < num_fd_list;i++) > { > if (ioctl(fd_list[i].fd,FIONREAD,&nbytes) != 0) > fatal("ioctl() error in main(xfs)"); > if (nbytes > 0) > (*fd_list[i].routine) (i); > } > } I note three problems with this code immediately. 1) The descriptor masks will normally be changed by select(), so you should reconstruct readfds each time around the loop. 2) The last three arguments to select() are pointers; unless you don't care about portability to non-prototype-capable compilers, you should pass pointers. 3) You should *use* the descriptor mask returned by select. RTFM; when select returns the descriptor mask has been modified so that only those bits corresponding to ready-to-read file descriptors are set. A sketch of what it might look like after these changes, assuming numfds is correctly set (ie, is larger than all file descriptors in the fd_list array): for (keep_going=TRUE;keep_going;) { FD_ZERO(&readfds); for (i=0;ifds[0]|=(1<<(fd))) #define FD_CLR(fd,set) ((set)->fds[0]&=~(1<<(fd))) #define FD_ISSET(fd,set) ((set)->fds[0]&(1<<(fd))) #define FD_ZERO(set) ((set)->fds[0]=0) #endif This include file is slightly nonportable (it passes a pointer to a structure instead of a pointer to int), but I believe all systems that run systems with select(), but without the correct macros, will accept it and run just fine. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu