Re: [Exim] 1.000.000 email delivered in single session

Páxina inicial
Borrar esta mensaxe
Responder a esta mensaxe
Autor: Exim Users Mailing List
Data:  
Para: Exim Users Mailing List
Asunto: Re: [Exim] 1.000.000 email delivered in single session
[ On Friday, November 2, 2001 at 16:22:43 (+0000), Philip Hazel wrote: ]
> Subject: Re: [Exim] 1.000.000 email delivered in single session
>
> Hmm. I suppose there's no harm in it. Clearly FreeBSD must be a system
> where setting SIG_IGN for a child does not automatically reap it. I
> suppose I'd better put this into the loop for incoming SMTP over TCP/IP
> as well. Sigh. <rant> Why is Unix so non-uniform? </rant>


The default action on *BSD (and POSIX and SuSv2) of SIGCHLD is SIG_IGN.

The reaping of unreaped zombie processes will normally be done by 'init'
on all Unixen too, but that can only happen if they are re-parented to
'init', and that can only happen if their own parent exits without
reaping them.

If you don't want to explicitly reap a child process when it exits then
you need to turn it into its own daemon -- i.e. reparent it so that it
has a PPID of 1. On *BSD you can do this with daemon(3) in the child,
but fundamentally it's just a matter of having the child fork twice, and
having the intermediate child exit right away. You can use vfork to do
the first fork too. In either case you have to be careful to use
_exit() in the intermediate child. The *BSD implementation also calls
setsid() in the final child, and can be told to chdir("/") and to
re-open the three stdio descriptors on /dev/null.

I find though that it's much better to explicitly catch SIGCHLD and call
one of the wait() family as appropriate from within the handler:

#ifdef HAVE_WAITPID
    while ((pid = waitpid(-1, (int *)0, WNOHANG)) > 0)
#else
# ifdef HAVE_WAIT3
    while ((pid = wait3((STATUS_TYPE *)0, WNOHANG, 0)) > 0)
# else
    if ((pid = wait((STATUS_TYPE *)0)) > 0)
# endif
#endif
    {
        reap_dead_child(pid);    /* i.e. record its death, etc. */
    }


Though with the WNOHANG it seems unreliable to to this, it would in fact
be more unreliable not to use it. If you call waitpid() from within the
SIGCHLD handler, and if the state change of a child process was that it
has exited, then there's guaranteed to always be a valid child process
to reap. SIGCHLD will also happen if the child is stopped, etc., too,
and that's why you need the WNOHANG. On systems without waitpid() or
wait3() there's no job control so no huge worry of other such state
changes leaving you hanging.


This way you can also keep track of all the undead children and kill
then kindly when you've been told to shut down or whatever.

-- 
                            Greg A. Woods


+1 416 218-0098      VE3TCP      <gwoods@???>     <woods@???>
Planix, Inc. <woods@???>;   Secrets of the Weird <woods@???>