
Gregory Colvin wrote:
oh ? Any call to fork()
On systems that have fork().
should be accompagnied by a call to wait() (or one of its cousins such as 'waitpid()').
On systems that have wait().
yes, I'm only talking about posix systems.
The only question is whether that has to happen synchronously or asynchronously.
And that question could be answered by the process library, or left to the user.
I believe this should be left to the user. However, it would be nice if the library had some way of encapsulating various strategies to execute non-reentrant callbacks in a safe (and of course portable) way.
Calling 'wait()' synchronously basically means to block right after 'fork()' has been called untill the child process terminates. One technique that uses this approach is to detach the subprocess, i.e. to fork twice, and while the grand-child carries out the actual task, the child finishes immediately.
Which won't work if the parent cares about the child's exit() value?
of course not. The above is used to implement demons.
The much more frequent situation is to call it asynchronously, i.e. the call would be either executed from inside the SIGCHLD handler or somehow triggered by it (such as a semaphore, which is reentrant).
Which was the implementation Angus first suggested, which a few of us pointed out was unsafe as written. I meant to suggest the choice could be left to the user.
You can also avoid blocking with a separate thread to do the wait(),
that doesn't sound good: each sub-process would have to be accompagnied by a thread...that's quite a lot of unnecessary overhead, especially since any reentrant solution would be able to dispatch all sigchilds from a single handler, i.e. the cost would be constant and not dependent on the number of child processes.
or by calling waitpid() with WNOHANG in a polling loop.
that's even more expensive. I think, any efficient solution to this problem will be quite intrusive, i.e. it won't be possible to provide some sort of black box which you hand over a callback. It needs tight integration with the rest of the application such as an event loop or a general purpose signal handler (I used to run one thread per application to be responsible for all signals the process could possibly catch (well, beside those that are thread-bound)). Probably the closest what you can get in terms of flexibility / portability is ACE, as was already pointed out earlier. But that's a huge framework, both, in terms of scope as well as code. That's the kind of scope though at which such a facility is best implemented. Regards, Stefan