exit-time debug
[users/jgh/exim.git] / src / src / exim.c
index 63ac620e7b1351b36e4d73294a809d4486e9fbdf..7b1c8ead972c8a33ac8ad5758cc37328d55699c7 100644 (file)
@@ -309,6 +309,7 @@ milliwait(struct itimerval *itval)
 {
 sigset_t sigmask;
 sigset_t old_sigmask;
+int save_errno = errno;
 
 if (itval->it_value.tv_usec < 50 && itval->it_value.tv_sec == 0)
   return;
@@ -322,6 +323,8 @@ if (setitimer(ITIMER_REAL, itval, NULL) < 0)           /* Start timer */
 (void)sigdelset(&sigmask, SIGALRM);                    /* Remove SIGALRM */
 (void)sigsuspend(&sigmask);                            /* Until SIGALRM */
 (void)sigprocmask(SIG_SETMASK, &old_sigmask, NULL);    /* Restore mask */
+errno = save_errno;
+sigalrm_seen = FALSE;
 }
 
 
@@ -342,11 +345,9 @@ Returns:     nothing
 void
 millisleep(int msec)
 {
-struct itimerval itval;
-itval.it_interval.tv_sec = 0;
-itval.it_interval.tv_usec = 0;
-itval.it_value.tv_sec = msec/1000;
-itval.it_value.tv_usec = (msec % 1000) * 1000;
+struct itimerval itval = {.it_interval = {.tv_sec = 0, .tv_usec = 0},
+                         .it_value = {.tv_sec = msec/1000,
+                                      .tv_usec = (msec % 1000) * 1000}};
 milliwait(&itval);
 }
 
@@ -714,14 +715,14 @@ Returns:     does not return
 */
 
 void
-exim_exit(int rc, const uschar * process)
+exim_exit(int rc)
 {
 search_tidyup();
 store_exit();
 DEBUG(D_any)
-  debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d %s%s%sterminating with rc=%d "
-    ">>>>>>>>>>>>>>>>\n", (int)getpid(),
-    process ? "(" : "", process, process ? ") " : "", rc);
+  debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d (%s) terminating with rc=%d "
+    ">>>>>>>>>>>>>>>>\n",
+    (int)getpid(), process_purpose, rc);
 exit(rc);
 }
 
@@ -730,6 +731,10 @@ void
 exim_underbar_exit(int rc)
 {
 store_exit();
+DEBUG(D_any)
+  debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d (%s) terminating with rc=%d "
+    ">>>>>>>>>>>>>>>>\n",
+    (int)getpid(), process_purpose, rc);
 _exit(rc);
 }
 
@@ -2755,6 +2760,13 @@ for (i = 1; i < argc; i++)
 
        case 'D': smtp_peer_options |= OPTION_DSN; break;
 
+    /* -MCd: for debug, set a process-purpose string */
+
+       case 'd': if (++i < argc)
+                   process_purpose = string_copy_taint(argv[i], TRUE);
+                 else badarg = TRUE;
+                 break;
+
     /* -MCG: set the queue name, to a non-default value */
 
        case 'G': if (++i < argc) queue_name = string_copy(argv[i]);
@@ -4429,7 +4441,7 @@ if (test_retry_arg >= 0)
   if (test_retry_arg >= argc)
     {
     printf("-brt needs a domain or address argument\n");
-    exim_exit(EXIT_FAILURE, US"main");
+    exim_exit(EXIT_FAILURE);
     }
   s1 = argv[test_retry_arg++];
   s2 = NULL;
@@ -4534,7 +4546,7 @@ if (test_retry_arg >= 0)
 
     printf("\n");
     }
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS);
   }
 
 /* Handle a request to list one or more configuration options */
@@ -4561,14 +4573,14 @@ if (list_options)
     else
       fail = !readconf_print(argv[i], NULL, flag_n);
     }
-  exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS, US"main");
+  exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
   }
 
 if (list_config)
   {
   set_process_info("listing config");
   exim_exit(readconf_print(US"config", NULL, flag_n)
-               ? EXIT_SUCCESS : EXIT_FAILURE, US"main");
+               ? EXIT_SUCCESS : EXIT_FAILURE);
   }
 
 
@@ -4594,7 +4606,7 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD)
   if (prod_requires_admin && !f.admin_user)
     {
     fprintf(stderr, "exim: Permission denied\n");
-    exim_exit(EXIT_FAILURE, US"main");
+    exim_exit(EXIT_FAILURE);
     }
   set_process_info("delivering specified messages");
   if (deliver_give_up) forced_delivery = f.deliver_force_thaw = TRUE;
@@ -4604,7 +4616,7 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD)
     pid_t pid;
     if (i == argc - 1)
       (void)deliver_message(argv[i], forced_delivery, deliver_give_up);
-    else if ((pid = fork()) == 0)
+    else if ((pid = exim_fork(US"cmdline-delivery")) == 0)
       {
       (void)deliver_message(argv[i], forced_delivery, deliver_give_up);
       exim_underbar_exit(EXIT_SUCCESS);
@@ -4613,11 +4625,11 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD)
       {
       fprintf(stderr, "failed to fork delivery process for %s: %s\n", argv[i],
         strerror(errno));
-      exim_exit(EXIT_FAILURE, US"main");
+      exim_exit(EXIT_FAILURE);
       }
     else wait(&status);
     }
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS);
   }
 
 
@@ -4627,16 +4639,16 @@ turn into a queue runner, with an optional starting message id. */
 if (queue_interval == 0 && !f.daemon_listen)
   {
   DEBUG(D_queue_run) debug_printf("Single queue run%s%s%s%s\n",
-    (start_queue_run_id == NULL)? US"" : US" starting at ",
-    (start_queue_run_id == NULL)? US"" : start_queue_run_id,
-    (stop_queue_run_id == NULL)?  US"" : US" stopping at ",
-    (stop_queue_run_id == NULL)?  US"" : stop_queue_run_id);
+    start_queue_run_id ? US" starting at " : US"",
+    start_queue_run_id ? start_queue_run_id: US"",
+    stop_queue_run_id ?  US" stopping at " : US"",
+    stop_queue_run_id ?  stop_queue_run_id : US"");
   if (*queue_name)
     set_process_info("running the '%s' queue (single queue run)", queue_name);
   else
     set_process_info("running the queue (single queue run)");
   queue_run(start_queue_run_id, stop_queue_run_id, FALSE);
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS);
   }
 
 
@@ -4806,10 +4818,10 @@ if (test_rewrite_arg >= 0)
   if (test_rewrite_arg >= argc)
     {
     printf("-brw needs an address argument\n");
-    exim_exit(EXIT_FAILURE, US"main");
+    exim_exit(EXIT_FAILURE);
     }
   rewrite_test(argv[test_rewrite_arg]);
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS);
   }
 
 /* A locally-supplied message is considered to be coming from a local user
@@ -4924,7 +4936,7 @@ if (verify_address_mode || f.address_test_mode)
     }
 
   route_tidyup();
-  exim_exit(exit_value, US"main");
+  exim_exit(exit_value);
   }
 
 /* Handle expansion checking. Either expand items on the command line, or read
@@ -5010,7 +5022,7 @@ if (expansion_test)
     deliver_datafile = -1;
     }
 
-  exim_exit(EXIT_SUCCESS, US"main: expansion test");
+  exim_exit(EXIT_SUCCESS);
   }
 
 
@@ -5104,7 +5116,7 @@ if (host_checking)
       }
     smtp_log_no_mail();
     }
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS);
   }
 
 
@@ -5267,7 +5279,7 @@ if (smtp_input)
   if (!smtp_start_session())
     {
     mac_smtp_fflush();
-    exim_exit(EXIT_SUCCESS, US"smtp_start toplevel");
+    exim_exit(EXIT_SUCCESS);
     }
   }
 
@@ -5382,14 +5394,14 @@ while (more)
        cancel_cutthrough_connection(TRUE, US"receive dropped");
         if (more) goto moreloop;
         smtp_log_no_mail();               /* Log no mail if configured */
-        exim_exit(EXIT_FAILURE, US"receive toplevel");
+        exim_exit(EXIT_FAILURE);
         }
       }
     else
       {
       cancel_cutthrough_connection(TRUE, US"message setup dropped");
       smtp_log_no_mail();               /* Log no mail if configured */
-      exim_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS, US"msg setup toplevel");
+      exim_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
       }
     }
 
@@ -5439,7 +5451,7 @@ while (more)
           if (error_handling == ERRORS_STDERR)
             {
             fprintf(stderr, "exim: too many recipients\n");
-            exim_exit(EXIT_FAILURE, US"main");
+            exim_exit(EXIT_FAILURE);
             }
           else
             return
@@ -5473,7 +5485,7 @@ while (more)
             {
             fprintf(stderr, "exim: bad recipient address \"%s\": %s\n",
               string_printing(list[i]), errmess);
-            exim_exit(EXIT_FAILURE, US"main");
+            exim_exit(EXIT_FAILURE);
             }
           else
             {
@@ -5545,7 +5557,7 @@ while (more)
     for real; when reading the headers of a message for filter testing,
     it is TRUE if the headers were terminated by '.' and FALSE otherwise. */
 
-    if (message_id[0] == 0) exim_exit(EXIT_FAILURE, US"main");
+    if (message_id[0] == 0) exim_exit(EXIT_FAILURE);
     }  /* Non-SMTP message reception */
 
   /* If this is a filter testing run, there are headers in store, but
@@ -5590,7 +5602,7 @@ while (more)
     if (chdir("/"))   /* Get away from wherever the user is running this from */
       {
       DEBUG(D_receive) debug_printf("chdir(\"/\") failed\n");
-      exim_exit(EXIT_FAILURE, US"main");
+      exim_exit(EXIT_FAILURE);
       }
 
     /* Now we run either a system filter test, or a user filter test, or both.
@@ -5600,15 +5612,15 @@ while (more)
 
     if ((filter_test & FTEST_SYSTEM) != 0)
       if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more))
-        exim_exit(EXIT_FAILURE, US"main");
+        exim_exit(EXIT_FAILURE);
 
     memcpy(filter_sn, filter_n, sizeof(filter_sn));
 
     if ((filter_test & FTEST_USER) != 0)
       if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
-        exim_exit(EXIT_FAILURE, US"main");
+        exim_exit(EXIT_FAILURE);
 
-    exim_exit(EXIT_SUCCESS, US"main");
+    exim_exit(EXIT_SUCCESS);
     }
 
   /* Else act on the result of message reception. We should not get here unless
@@ -5690,7 +5702,7 @@ while (more)
     pid_t pid;
     search_tidyup();
 
-    if ((pid = fork()) == 0)
+    if ((pid = exim_fork(US"local-accept-delivery")) == 0)
       {
       int rc;
       close_unwanted();      /* Close unwanted file descriptors and TLS */
@@ -5734,7 +5746,7 @@ while (more)
          log_write(0, LOG_MAIN|LOG_PANIC,
            "process %d crashed with signal %d while delivering %s",
            (int)pid, status & 0x00ff, message_id);
-       if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE, US"main");
+       if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE);
        }
       }
     }
@@ -5766,7 +5778,7 @@ moreloop:
   store_reset(reset_point);
   }
 
-exim_exit(EXIT_SUCCESS, US"main");   /* Never returns */
+exim_exit(EXIT_SUCCESS);   /* Never returns */
 return 0;                  /* To stop compiler warning */
 }