-/* $Cambridge: exim/src/src/daemon.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/daemon.c,v 1.3 2004/11/11 16:03:47 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
main_sigchld_handler(int sig)
{
sig = sig; /* Keep picky compilers happy */
+os_non_restarting_signal(SIGCHLD, SIG_DFL);
sigchld_seen = TRUE;
-signal(SIGCHLD, SIG_DFL);
}
int i;
int queue_only_reason = 0;
int old_pool = store_pool;
+ int save_debug_selector = debug_selector;
BOOL local_queue_only;
#ifdef SA_NOCLDWAIT
struct sigaction act;
/* Attempt to get an id from the sending machine via the RFC 1413
protocol. We do this in the sub-process in order not to hold up the
main process if there is any delay. Then set up the fullhost information
- in case there is no HELO/EHLO. */
-
+ in case there is no HELO/EHLO.
+
+ If debugging is enabled only for the daemon, we must turn if off while
+ finding the id, but turn it on again afterwards so that information about the
+ incoming connection is output. */
+
+ if (debug_daemon) debug_selector = 0;
verify_get_ident(IDENT_PORT);
host_build_sender_fullhost();
+ debug_selector = save_debug_selector;
DEBUG(D_any)
debug_printf("Process %d is handling incoming connection from %s\n",
(int)getpid(), sender_fullhost);
+ /* Now disable debugging permanently if it's required only for the daemon
+ process. */
+
+ if (debug_daemon) debug_selector = 0;
+
/* If there are too many child processes for immediate delivery,
set the local_queue_only flag, which is initialized from the
configured value and may therefore already be TRUE. Leave logging
/* Set up the handler for termination of child processes. */
sigchld_seen = FALSE;
-signal(SIGCHLD, main_sigchld_handler);
+os_non_restarting_signal(SIGCHLD, main_sigchld_handler);
/* If we are to run the queue periodically, pretend the alarm has just gone
off. This will cause the first queue-runner to get kicked off straight away. */
if ((pid = fork()) == 0)
{
int sk;
+
DEBUG(D_any) debug_printf("Starting queue-runner: pid %d\n",
(int)getpid());
+ /* Disable debugging if it's required only for the daemon process. We
+ leave the above message, because it ties up with the "child ended"
+ debugging messages. */
+
+ if (debug_daemon) debug_selector = 0;
+
/* Close any open listening sockets in the child */
for (sk = 0; sk < listen_socket_count; sk++) close(listen_sockets[sk]);
}
DEBUG(D_any) debug_printf("Listening...\n");
+
+ /* In rare cases we may have had a SIGCHLD signal in the time between
+ setting the handler (below) and getting back here. If so, pretend that the
+ select() was interrupted so that we reap the child. This might still leave
+ a small window when a SIGCHLD could get lost. However, since we use SIGCHLD
+ only to do the reaping more quickly, it shouldn't result in anything other
+ than a delay until something else causes a wake-up. */
+
+ if (sigchld_seen)
+ {
+ lcount = -1;
+ errno = EINTR;
+ }
+ else
+ {
+ lcount = select(max_socket + 1, (SELECT_ARG2_TYPE *)&select_listen,
+ NULL, NULL, NULL);
+ }
- if ((lcount = select(max_socket + 1, (SELECT_ARG2_TYPE *)&select_listen,
- NULL, NULL, NULL)) < 0)
+ if (lcount < 0)
{
select_failed = TRUE;
lcount = 1;
}
-
+
/* Loop for all the sockets that are currently ready to go. If select
- actually failed, we have set the count to 1 and a flag, so as to use the
- common error code for select/accept below. */
+ actually failed, we have set the count to 1 and select_failed=TRUE, so as
+ to use the common error code for select/accept below. */
while (lcount-- > 0)
{
if (sigchld_seen)
{
sigchld_seen = FALSE;
- signal(SIGCHLD, main_sigchld_handler);
+ os_non_restarting_signal(SIGCHLD, main_sigchld_handler);
}
/* Handle being woken by SIGHUP. We know at this point that the result