(1) Typo in redirect router; (2) Update version number; (3) Update
[exim.git] / src / src / daemon.c
index d9375eabf2df79b7c1f6e4b82dedff24973b651a..dfd781116c019f1ae08bcfd42db4bec46f9c76b6 100644 (file)
@@ -1,10 +1,10 @@
-/* $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.4 2005/01/04 10:00:42 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with running Exim as a daemon */
@@ -84,8 +84,8 @@ static void
 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);
 }
 
 
@@ -362,6 +362,7 @@ if (pid == 0)
   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;
@@ -432,15 +433,26 @@ if (pid == 0)
   /* 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
@@ -1365,7 +1377,7 @@ if (queue_interval > 0 && queue_run_max > 0)
 /* 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. */
@@ -1511,9 +1523,16 @@ for (;;)
       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]);
@@ -1605,17 +1624,34 @@ for (;;)
       }
 
     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)
       {
@@ -1766,7 +1802,7 @@ for (;;)
   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