Path: utzoo!mnetor!uunet!seismo!sundc!pitstop!sun!betelgeuse!jamesa From: jamesa%betelgeuse@Sun.COM (James D. Allen) Newsgroups: comp.unix.wizards Subject: Re: Wait, Select, and a SIGCHLD Race Condition Message-ID: <36350@sun.uucp> Date: 13 Dec 87 23:45:32 GMT References: <5105@sol.ARPA> Sender: news@sun.uucp Lines: 56 Summary: Longjmp also works In article <5105@sol.ARPA>, stuart@cs.rochester.edu writes: > I need advice (or sympathy) for handling a race condition in 4.3BSD > flavored UNIX. Briefly, I want to use wait3 to reap all the dead or > stopped children of a process, then use select to wait for the first > new IO or child activity. Sketch something like this: > > while (0 < (pid = wait3(..., WNOHANG, ...))) { > /* do something with child */ > } > /* XXX Race condition is here */ > numfds = select(...); et cetera 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. Two correct solutions have been posted which take advantage of a Unix feature (FASYNC in one case, select timeout in the other). It's worth noting, however, that the application code can detect and fix the race without OS assistance, as shown in the crude fragment: sig_catcher() { caught_signal = TRUE; if (possible_race) longjmp(jmp_buffer, 1); } wait_for_event() { ... if (setjmp(jmp_buffer)) { signalled: possible_race = FALSE; /* process the signal */ caught_signal = FALSE; } else { possible_race = TRUE; if (caught_signal) goto signalled; numfds = select(...); /* * No longer need to check EINTR!! * if (numfds < 0 && errno == EINTR) * goto signalled; */ possible_race = FALSE; /* process the select */ } ... } I don't know how to do this without `longjmp' (or something even uglier). > > Stu Friedberg {ames,cmcl2,rutgers}!rochester!stuart stuart@cs.rochester.edu James Allen {ucbvax,hplabs,seismo}!sun!betelgeuse!jamesa