Vadim Vygonets writes:
> Quoth Philip Hazel on Wed, May 26, 1999:
> > An exim queue-runner is supposed to do serial delivery, one message at a
> > time. If it starts up a process that delivers down an SMTP channel, and
> > that process hands the open channel on to a 3rd process and then exits,
> > the queue runner must not continue until the 3rd process has finished.
[...]
> Well, AFAIK, there's no way to wait for your grandchild. Some
> other possibilities exist, e.g., before Q (the queue runner)
> forks process B, it can create a pipe from B to Q, and when B
> forks C, C will get the write end of the pipe from B. When C
> dies, the pipe is closed, and Q will get an EOF on it. So when Q
> has nothing to do, it can select(2) on the pipe.
>
> Granted, it's dirty.
That's the solution I came up with and I'd call it "elegant"
rather than "dirty" :-) The O/S keeps track of the reference
counting for you however many processes you fire off (or a
process can close the descriptor if it doesn't want to participate
provided you pass it the descriptor number). When the very last
process involved dies, the O/S guarantees to let you know by
unblocking your select or else you can choose to have it send you a
SIGIO if you want to be notified asynchronously.
Another way would be via a SysV semaphore. After you fork but before
you exec, add one to the semaphore along with a SEM_UNDO so that it'll
be undone when the process dies. The ancenstral parent can then block
with a waiting semop until all processes involved have died (or test
with IPC_NOWAIT if you don't want to block). Although a semaphore
sounds like it ought to be a nicer solution, I'd consider the pipe one
better: more flexible, easier to implement and more Unixy.
--Malcolm
--
Malcolm Beattie <mbeattie@???>
Unix Systems Programmer
Oxford University Computing Services
--
*** Exim information can be found at
http://www.exim.org/ ***