Path: utzoo!mnetor!uunet!husc6!hao!ames!umd5!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.wizards Subject: Re: Wait, Select, and a SIGCHLD Race Condition Message-ID: <9771@mimsy.UUCP> Date: 14 Dec 87 19:30:10 GMT References: <5105@sol.ARPA> <36350@sun.uucp> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 85 In article <36350@sun.uucp> jamesa%betelgeuse@Sun.COM (James D. Allen) writes: >This race condition is intriguing because it arises from "instruction >atomization" in the application program, and NOT due to limitations in the >Unix system interface. All user-level race conditions result from this; it can be (but does not have to be) considered a deficiency in the interface. This very problem is precisely why I want a signal mask in select's arguments: so that none of the three kludges are necessary. (Some of you may recall my recent diatribe on the subject.) In summary: FASYNC select timeout longjmp The first method works only if you are willing to recode everything to use signals (and you still need select!---but with immediate timeout); the select timeout works but is somewhat tricky to code; the longjmp works but only if you have exactly one jump. I would probably use the select timeout trick myself. Here it is in its full glory: struct select_goo { int *nfds; /* points to select's nfds argument */ struct timeval *timeout; /* ... to timeout argument */ struct select_goo *inner; /* previous select, if recursing */ } *select_goo; catch_sigchld() { child_changed = 1; if (select_goo) { *select_goo->nfds = 0; /* saves work in select() */ timerclear(select_goo->timeout); } } ... int nfds, omask, cc; fd_set rfd, wfd, xfd; struct timeval to; struct select_goo goo; /* copy these since select or SIGCHLD will modify them */ nfds = Nfds, rfd = Rfd, wfd = Wfd, xfd = Xfd, to = Timeout; /* hold the signal while we build the goo */ omask = sigblock(sigmask(SIGCHLD)); if (child_changed) { /* a signal already occurred, so skip all this */ (void) sigsetmask(omask); return (0); } goo.nfds = &nfds; goo.timeout = &to; goo.inner = select_goo; select_goo = &goo; /* now safe to release the signal */ (void) sigsetmask(omask); cc = select(nfds, &rfd, &wfd, &xfd, &to); /* either the select selected, or the signal hit, or the timeout expired */ /* undo the goo */ omask = sigblock(sigmask(SIGCHLD)); select_goo = goo.inner; /* figure out which event occurred */ if (child_changed) { /* the signal hit */ } else if (cc == 0) { /* the timeout expired */ } else { /* the select selected */ } (void) sigsetmask(omask); -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris