summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2020-03-22 20:15:33 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2020-03-22 20:25:36 +0000
commit46d2a5e6f6e7709d172903b13945d23fc0a2c888 (patch)
tree11692101015bb85482f5105e46c1f7f8edfbc330 /src
parenteb763a7aaf9ed36939193283153724eb2671c999 (diff)
parent8102279385f5f70c959aa219feca37031c0a1828 (diff)
Merge branch 'debug_fork'
Diffstat (limited to 'src')
-rw-r--r--src/src/child.c47
-rw-r--r--src/src/daemon.c35
-rw-r--r--src/src/deliver.c30
-rw-r--r--src/src/dns.c5
-rw-r--r--src/src/exim.c89
-rw-r--r--src/src/expand.c3
-rw-r--r--src/src/functions.h51
-rw-r--r--src/src/globals.c1
-rw-r--r--src/src/globals.h1
-rw-r--r--src/src/local_scan.h37
-rw-r--r--src/src/log.c14
-rw-r--r--src/src/moan.c13
-rw-r--r--src/src/queue.c14
-rw-r--r--src/src/rda.c4
-rw-r--r--src/src/readconf.c6
-rw-r--r--src/src/receive.c8
-rw-r--r--src/src/route.c6
-rw-r--r--src/src/routers/queryprogram.c6
-rw-r--r--src/src/sieve.c28
-rw-r--r--src/src/smtp_in.c13
-rw-r--r--src/src/tls.c4
-rw-r--r--src/src/transport.c25
-rw-r--r--src/src/transports/autoreply.c8
-rw-r--r--src/src/transports/lmtp.c6
-rw-r--r--src/src/transports/pipe.c5
-rw-r--r--src/src/transports/smtp.c16
26 files changed, 260 insertions, 215 deletions
diff --git a/src/src/child.c b/src/src/child.c
index c5054b6fb..5e4b978cd 100644
--- a/src/src/child.c
+++ b/src/src/child.c
@@ -75,7 +75,7 @@ int n = 0;
int extra = pcount ? *pcount : 0;
uschar **argv;
-argv = store_get((extra + acount + MAX_CLMACROS + 19) * sizeof(char *), FALSE);
+argv = store_get((extra + acount + MAX_CLMACROS + 21) * sizeof(char *), FALSE);
/* In all case, the list starts out with the path, any macros, and a changed
config file. */
@@ -109,6 +109,11 @@ if (!minimal)
if (debug_selector != 0)
argv[n++] = string_sprintf("-d=0x%x", debug_selector);
}
+ DEBUG(D_any)
+ {
+ argv[n++] = US"-MCd";
+ argv[n++] = US process_purpose;
+ }
if (!f.testsuite_delays) argv[n++] = US"-odd";
if (f.dont_deliver) argv[n++] = US"-N";
if (f.queue_smtp) argv[n++] = US"-odqs";
@@ -140,7 +145,7 @@ if (acount > 0)
argv[n] = NULL;
if (exec_type == CEE_RETURN_ARGV)
{
- if (pcount != NULL) *pcount = n;
+ if (pcount) *pcount = n;
return argv;
}
@@ -185,13 +190,15 @@ to exist, even if all calls from within Exim are changed, because it is
documented for use from local_scan().
Argument: fdptr pointer to int for the stdin fd
+ purpose of the child process, for debug
Returns: pid of the created process or -1 if anything has gone wrong
*/
pid_t
-child_open_exim(int *fdptr)
+child_open_exim_function(int * fdptr, const uschar * purpose)
{
-return child_open_exim2(fdptr, US"<>", bounce_sender_authentication);
+return child_open_exim2_function(fdptr, US"<>", bounce_sender_authentication,
+ purpose);
}
@@ -202,12 +209,14 @@ Arguments:
fdptr pointer to int for the stdin fd
sender for a sender address (data for -f)
sender_authentication authenticated sender address or NULL
+ purpose of the child process, for debug
Returns: pid of the created process or -1 if anything has gone wrong
*/
pid_t
-child_open_exim2(int *fdptr, uschar *sender, uschar *sender_authentication)
+child_open_exim2_function(int * fdptr, uschar * sender,
+ uschar * sender_authentication, const uschar * purpose)
{
int pfd[2];
int save_errno;
@@ -220,7 +229,7 @@ on the wait. */
if (pipe(pfd) != 0) return (pid_t)(-1);
oldsignal = signal(SIGCHLD, SIG_DFL);
-pid = fork();
+pid = exim_fork(purpose);
/* Child process: make the reading end of the pipe into the standard input and
close the writing end. If debugging, pass debug_fd as stderr. Then re-exec
@@ -236,7 +245,7 @@ if (pid == 0)
if (debug_fd > 0) force_fd(debug_fd, 2);
if (f.running_in_test_harness && !queue_only)
{
- if (sender_authentication != NULL)
+ if (sender_authentication)
child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 9,
US "-odi", US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
sender_authentication, message_id_option);
@@ -248,7 +257,7 @@ if (pid == 0)
}
else /* Not test harness */
{
- if (sender_authentication != NULL)
+ if (sender_authentication)
child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 8,
US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
sender_authentication, message_id_option);
@@ -309,6 +318,7 @@ Arguments:
process is placed
wd if not NULL, a path to be handed to chdir() in the new process
make_leader if TRUE, make the new process a process group leader
+ purpose for debug: reason for running the task
Returns: the pid of the created process or -1 if anything has gone wrong
*/
@@ -316,7 +326,7 @@ Returns: the pid of the created process or -1 if anything has gone wrong
pid_t
child_open_uid(const uschar **argv, const uschar **envp, int newumask,
uid_t *newuid, gid_t *newgid, int *infdptr, int *outfdptr, uschar *wd,
- BOOL make_leader)
+ BOOL make_leader, const uschar * purpose)
{
int save_errno;
int inpfd[2], outpfd[2];
@@ -337,7 +347,7 @@ that the child process can be waited for. We sometimes get here with it set
otherwise. Save the old state for resetting on the wait. */
oldsignal = signal(SIGCHLD, SIG_DFL);
-pid = fork();
+pid = exim_fork(purpose);
/* Handle the child process. First, set the required environment. We must do
this before messing with the pipes, in order to be able to write debugging
@@ -348,14 +358,14 @@ if (pid == 0)
signal(SIGUSR1, SIG_IGN);
signal(SIGPIPE, SIG_DFL);
- if (newgid != NULL && setgid(*newgid) < 0)
+ if (newgid && setgid(*newgid) < 0)
{
DEBUG(D_any) debug_printf("failed to set gid=%ld in subprocess: %s\n",
(long int)(*newgid), strerror(errno));
goto CHILD_FAILED;
}
- if (newuid != NULL && setuid(*newuid) < 0)
+ if (newuid && setuid(*newuid) < 0)
{
DEBUG(D_any) debug_printf("failed to set uid=%ld in subprocess: %s\n",
(long int)(*newuid), strerror(errno));
@@ -364,7 +374,7 @@ if (pid == 0)
(void)umask(newumask);
- if (wd != NULL && Uchdir(wd) < 0)
+ if (wd && Uchdir(wd) < 0)
{
DEBUG(D_any) debug_printf("failed to chdir to %s: %s\n", wd,
strerror(errno));
@@ -394,8 +404,8 @@ if (pid == 0)
/* Now do the exec */
- if (envp == NULL) execv(CS argv[0], (char *const *)argv);
- else execve(CS argv[0], (char *const *)argv, (char *const *)envp);
+ if (envp) execve(CS argv[0], (char *const *)argv, (char *const *)envp);
+ else execv(CS argv[0], (char *const *)argv);
/* Failed to execv. Signal this failure using EX_EXECFAILED. We are
losing the actual errno we got back, because there is no way to return
@@ -450,16 +460,17 @@ Arguments:
outfdptr pointer to int into which the fd of the stdout/stderr of the new
process is placed
make_leader if TRUE, make the new process a process group leader
+ purpose for debug: reason for running the task
Returns: the pid of the created process or -1 if anything has gone wrong
*/
pid_t
-child_open(uschar **argv, uschar **envp, int newumask, int *infdptr,
- int *outfdptr, BOOL make_leader)
+child_open_function(uschar **argv, uschar **envp, int newumask, int *infdptr,
+ int *outfdptr, BOOL make_leader, const uschar * purpose)
{
return child_open_uid(CUSS argv, CUSS envp, newumask, NULL, NULL,
- infdptr, outfdptr, NULL, make_leader);
+ infdptr, outfdptr, NULL, make_leader, purpose);
}
diff --git a/src/src/daemon.c b/src/src/daemon.c
index aa36a5dc9..1a747af79 100644
--- a/src/src/daemon.c
+++ b/src/src/daemon.c
@@ -367,7 +367,7 @@ if (LOGGING(smtp_connection))
expansion above did a lookup. */
search_tidyup();
-pid = fork();
+pid = exim_fork(US"daemon-accept");
/* Handle the child process */
@@ -418,7 +418,7 @@ if (pid == 0)
"please try again later.\r\n", FALSE);
mac_smtp_fflush();
search_tidyup();
- exim_underbar_exit(EXIT_FAILURE, US"conn-accept");
+ exim_underbar_exit(EXIT_FAILURE);
}
}
else if (*nah) smtp_active_hostname = nah;
@@ -505,7 +505,7 @@ if (pid == 0)
{
mac_smtp_fflush();
search_tidyup();
- exim_underbar_exit(EXIT_SUCCESS, US"conn-smtp");
+ exim_underbar_exit(EXIT_SUCCESS);
}
for (;;)
@@ -533,7 +533,7 @@ if (pid == 0)
cancel_cutthrough_connection(TRUE, US"receive dropped");
mac_smtp_fflush();
smtp_log_no_mail(); /* Log no mail if configured */
- exim_underbar_exit(EXIT_SUCCESS, US"conn-receive");
+ exim_underbar_exit(EXIT_SUCCESS);
}
if (message_id[0] == 0) continue; /* No message was accepted */
}
@@ -556,7 +556,7 @@ if (pid == 0)
/*XXX should we pause briefly, hoping that the client will be the
active TCP closer hence get the TCP_WAIT endpoint? */
DEBUG(D_receive) debug_printf("SMTP>>(close on process exit)\n");
- exim_underbar_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS, US"conn-setup");
+ exim_underbar_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
}
/* Show the recipients when debugging */
@@ -663,7 +663,7 @@ if (pid == 0)
mac_smtp_fflush();
- if ((dpid = fork()) == 0)
+ if ((dpid = exim_fork(US"daemon-accept-delivery")) == 0)
{
(void)fclose(smtp_in);
(void)fclose(smtp_out);
@@ -692,7 +692,7 @@ if (pid == 0)
(void) deliver_message(message_id, FALSE, FALSE);
search_tidyup();
- exim_underbar_exit(EXIT_SUCCESS, US"deliver_msg");
+ exim_underbar_exit(EXIT_SUCCESS);
}
if (dpid > 0)
@@ -954,7 +954,7 @@ else
DEBUG(D_any)
debug_printf("%s\n", string_open_failed(errno, "pid file %s",
pid_file_path));
-exim_exit(EXIT_SUCCESS, US"pid file remover");
+exim_exit(EXIT_SUCCESS);
}
@@ -981,7 +981,7 @@ if (daemon_notifier_fd >= 0)
if (f.running_in_test_harness || write_pid)
{
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"daemon-del-pidfile")) == 0)
{
if (override_pid_file_path)
(void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, FALSE, 3,
@@ -994,7 +994,7 @@ if (f.running_in_test_harness || write_pid)
if (pid > 0)
child_close(pid, 1);
}
-exim_exit(EXIT_SUCCESS, US"daemon");
+exim_exit(EXIT_SUCCESS);
}
@@ -1200,6 +1200,8 @@ ip_address_item *addresses = NULL;
time_t last_connection_time = (time_t)0;
int local_queue_run_max = atoi(CS expand_string(queue_run_max));
+process_purpose = US"daemon";
+
/* If any debugging options are set, turn on the D_pid bit so that all
debugging lines get the pid added. */
@@ -1601,7 +1603,7 @@ if (f.background_daemon)
if (getppid() != 1)
{
- pid_t pid = fork();
+ pid_t pid = exim_fork(US"daemon");
if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
"fork() failed when starting daemon: %s", strerror(errno));
if (pid > 0) exit(EXIT_SUCCESS); /* in parent process, just exit */
@@ -2127,14 +2129,11 @@ for (;;)
have enough queue runners on the go. If we are not running as root, a
re-exec is required. */
- if (queue_interval > 0 &&
- (local_queue_run_max <= 0 || queue_run_count < local_queue_run_max))
+ if ( queue_interval > 0
+ && (local_queue_run_max <= 0 || queue_run_count < local_queue_run_max))
{
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"queue-runner")) == 0)
{
- 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. */
@@ -2221,7 +2220,7 @@ for (;;)
else
#endif
queue_run(NULL, NULL, FALSE);
- exim_underbar_exit(EXIT_SUCCESS, US"queue-runner");
+ exim_underbar_exit(EXIT_SUCCESS);
}
if (pid < 0)
diff --git a/src/src/deliver.c b/src/src/deliver.c
index 5c5167b3a..1748c7985 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -2268,7 +2268,7 @@ a clean slate and doesn't interfere with the parent process. */
search_tidyup();
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"delivery-local")) == 0)
{
BOOL replicate = TRUE;
@@ -2615,7 +2615,7 @@ if (addr->special_action == SPECIAL_WARN && addr->transport->warn_message)
"message for %s transport): %s", addr->transport->warn_message,
addr->transport->name, expand_string_message);
- else if ((pid = child_open_exim(&fd)) > 0)
+ else if ((pid = child_open_exim(&fd, US"tpt-warning-message")) > 0)
{
FILE *f = fdopen(fd, "wb");
if (errors_reply_to && !contains_header(US"Reply-To", warn_message))
@@ -4646,8 +4646,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
search_tidyup();
- DEBUG(D_deliver) debug_printf("forking transport process\n");
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"transport")) == 0)
{
int fd = pfd[pipe_write];
host_item *h;
@@ -4661,10 +4660,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
/* Show pids on debug output if parallelism possible */
if (parmax > 1 && (parcount > 0 || addr_remote))
- {
DEBUG(D_any|D_v) debug_selector |= D_pid;
- DEBUG(D_deliver) debug_printf("Remote delivery process started\n");
- }
/* Reset the random number generator, so different processes don't all
have the same sequence. In the test harness we want different, but
@@ -4977,7 +4973,6 @@ all pipes, so I do not see a reason to use non-blocking IO here
(void)close(fd);
exit(EXIT_SUCCESS);
}
- DEBUG(D_deliver) debug_printf("forked transport process (%d)\n", pid);
/* Back in the mainline: close the unwanted half of the pipe. */
@@ -7336,7 +7331,7 @@ if (addr_senddsn)
int fd;
/* create exim process to send message */
- pid = child_open_exim(&fd);
+ pid = child_open_exim(&fd, US"DSN");
DEBUG(D_deliver) debug_printf("DSN: child_open_exim returns: %d\n", pid);
@@ -7537,7 +7532,7 @@ while (addr_failed)
/* Make a subprocess to send a message */
- if ((pid = child_open_exim(&fd)) < 0)
+ if ((pid = child_open_exim(&fd, US"bounce-message")) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to "
"create child process to send failure message: %s", getpid(),
getppid(), strerror(errno));
@@ -7918,10 +7913,6 @@ wording. */
(void)fclose(fp);
rc = child_close(pid, 0); /* Waits for child to close, no timeout */
- /* In the test harness, let the child do it's thing first. */
-
- testharness_pause_ms(500);
-
/* If the process failed, there was some disaster in setting up the
error message. Unless the message is very old, ensure that addr_defer
is non-null, which will have the effect of leaving the message on the
@@ -8195,7 +8186,7 @@ else if (addr_defer != (address_item *)(+1))
{
header_line *h;
int fd;
- pid_t pid = child_open_exim(&fd);
+ pid_t pid = child_open_exim(&fd, US"delay-warning-message");
if (pid > 0)
{
@@ -8583,18 +8574,17 @@ if (cutthrough.cctx.sock >= 0 && cutthrough.callout_hold_only)
goto fail;
where = US"fork";
- if ((pid = fork()) < 0)
+ testharness_pause_ms(150);
+ if ((pid = exim_fork(US"tls-proxy-interproc")) < 0)
goto fail;
- else if (pid == 0) /* child: fork again to totally disconnect */
+ if (pid == 0) /* child: will fork again to totally disconnect */
{
- testharness_pause_ms(100); /* let parent debug out */
- /* does not return */
smtp_proxy_tls(cutthrough.cctx.tls_ctx, big_buffer, big_buffer_size,
pfd, 5*60);
+ /* does not return */
}
- DEBUG(D_transport) debug_printf("proxy-proc inter-pid %d\n", pid);
close(pfd[0]);
waitpid(pid, NULL, 0);
(void) close(channel_fd); /* release the client socket */
diff --git a/src/src/dns.c b/src/src/dns.c
index 6333d3cff..d036162cb 100644
--- a/src/src/dns.c
+++ b/src/src/dns.c
@@ -60,7 +60,8 @@ if (stat(CS utilname, &statbuf) >= 0)
int infd, outfd, rc;
uschar *argv[5];
- DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n", name, dns_text_type(type));
+ DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n",
+ name, dns_text_type(type));
argv[0] = utilname;
argv[1] = config_main_directory;
@@ -68,7 +69,7 @@ if (stat(CS utilname, &statbuf) >= 0)
argv[3] = dns_text_type(type);
argv[4] = NULL;
- pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE);
+ pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE, US"fakens-search");
if (pid < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to run fakens: %s",
strerror(errno));
diff --git a/src/src/exim.c b/src/src/exim.c
index 63ef40553..10526ba5f 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -345,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);
}
@@ -717,26 +715,26 @@ 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);
}
void
-exim_underbar_exit(int rc, const uschar * process)
+exim_underbar_exit(int rc)
{
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);
}
@@ -2747,6 +2745,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_taint(argv[i], TRUE);
@@ -4424,7 +4429,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;
@@ -4529,7 +4534,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 */
@@ -4556,14 +4561,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);
}
@@ -4589,7 +4594,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;
@@ -4601,20 +4606,20 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD)
that runs into a later copy into the untainted global message_id[] */
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, US"cmdline-delivery");
+ exim_underbar_exit(EXIT_SUCCESS);
}
else if (pid < 0)
{
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);
}
@@ -4633,7 +4638,7 @@ if (queue_interval == 0 && !f.daemon_listen)
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);
}
@@ -4803,10 +4808,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
@@ -4921,7 +4926,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
@@ -5007,7 +5012,7 @@ if (expansion_test)
deliver_datafile = -1;
}
- exim_exit(EXIT_SUCCESS, US"main: expansion test");
+ exim_exit(EXIT_SUCCESS);
}
@@ -5101,7 +5106,7 @@ if (host_checking)
}
smtp_log_no_mail();
}
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
@@ -5264,7 +5269,7 @@ if (smtp_input)
if (!smtp_start_session())
{
mac_smtp_fflush();
- exim_exit(EXIT_SUCCESS, US"smtp_start toplevel");
+ exim_exit(EXIT_SUCCESS);
}
}
@@ -5379,14 +5384,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);
}
}
@@ -5436,7 +5441,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
@@ -5469,7 +5474,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
{
@@ -5540,7 +5545,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
@@ -5585,7 +5590,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.
@@ -5595,15 +5600,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
@@ -5685,7 +5690,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 */
@@ -5705,7 +5710,7 @@ while (more)
rc = deliver_message(message_id, FALSE, FALSE);
search_tidyup();
exim_underbar_exit(!mua_wrapper || rc == DELIVER_MUA_SUCCEEDED
- ? EXIT_SUCCESS : EXIT_FAILURE, US"cmdline-delivery");
+ ? EXIT_SUCCESS : EXIT_FAILURE);
}
if (pid < 0)
@@ -5729,7 +5734,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);
}
}
}
@@ -5761,7 +5766,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 */
}
diff --git a/src/src/expand.c b/src/src/expand.c
index 4377ea1aa..fddad3179 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -5624,7 +5624,8 @@ while (*s != 0)
/* Create the child process, making it a group leader. */
- if ((pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE)) < 0)
+ if ((pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE,
+ US"expand-run")) < 0)
{
expand_string_message =
string_sprintf("couldn't create child process: %s", strerror(errno));
diff --git a/src/src/functions.h b/src/src/functions.h
index 0e38030d0..035960646 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -150,8 +150,13 @@ extern void bits_set(unsigned int *, size_t, int *);
extern void cancel_cutthrough_connection(BOOL, const uschar *);
extern int check_host(void *, const uschar *, const uschar **, uschar **);
extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
+extern pid_t child_open_exim_function(int *, const uschar *);
+extern pid_t child_open_exim2_function(int *, uschar *, uschar *,
+ const uschar *);
+extern pid_t child_open_function(uschar **, uschar **, int,
+ int *, int *, BOOL, const uschar *);
extern pid_t child_open_uid(const uschar **, const uschar **, int,
- uid_t *, gid_t *, int *, int *, uschar *, BOOL);
+ uid_t *, gid_t *, int *, int *, uschar *, BOOL, const uschar *);
extern BOOL cleanup_environment(void);
extern void cutthrough_data_puts(uschar *, int);
extern void cutthrough_data_put_nl(void);
@@ -222,10 +227,10 @@ extern void msg_event_raise(const uschar *, const address_item *);
extern int exim_chown_failure(int, const uschar*, uid_t, gid_t);
extern const uschar * exim_errstr(int);
-extern void exim_exit(int, const uschar *) NORETURN;
+extern void exim_exit(int) NORETURN;
extern void exim_nullstd(void);
extern void exim_setugid(uid_t, gid_t, BOOL, uschar *);
-extern void exim_underbar_exit(int, const uschar *);
+extern void exim_underbar_exit(int) NORETURN;
extern void exim_wait_tick(struct timeval *, int);
extern int exp_bool(address_item *addr,
uschar *mtype, uschar *mname, unsigned dgb_opt, uschar *oname, BOOL bvalue,
@@ -1099,6 +1104,46 @@ errno = EACCES;
return NULL;
}
+/******************************************************************************/
+/* Process manipulation */
+
+static inline pid_t
+exim_fork(const unsigned char * purpose)
+{
+pid_t pid;
+DEBUG(D_any) debug_printf("%s forking for %s\n", process_purpose, purpose);
+if ((pid = fork()) == 0)
+ {
+ process_purpose = purpose;
+ DEBUG(D_any) debug_printf("postfork: %s\n", purpose);
+ }
+else
+ {
+ testharness_pause_ms(100); /* let child work */
+ DEBUG(D_any) debug_printf("%s forked for %s: %d\n", process_purpose, purpose, (int)pid);
+ }
+return pid;
+}
+
+
+static inline pid_t
+child_open_exim(int * fdptr, const uschar * purpose)
+{ return child_open_exim_function(fdptr, purpose); }
+
+static inline pid_t
+child_open_exim2(int * fdptr, uschar * sender,
+ uschar * sender_auth, const uschar * purpose)
+{ return child_open_exim2_function(fdptr, sender, sender_auth, purpose); }
+
+static inline pid_t
+child_open(uschar **argv, uschar **envp, int newumask, int *infdptr,
+ int *outfdptr, BOOL make_leader, const uschar * purpose)
+{ return child_open_function(argv, envp, newumask, infdptr,
+ outfdptr, make_leader, purpose);
+}
+
+
+/******************************************************************************/
#endif /* !MACRO_PREDEF */
#endif /* _FUNCTIONS_H_ */
diff --git a/src/src/globals.c b/src/src/globals.c
index a771f1193..57f857e5a 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1188,6 +1188,7 @@ uschar *primary_hostname = NULL;
uschar *process_info;
int process_info_len = 0;
uschar *process_log_path = NULL;
+const uschar *process_purpose = US"fresh-exec";
#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
uschar *hosts_proxy = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index 28d170cdc..c9222743e 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -771,6 +771,7 @@ extern BOOL print_topbitchars; /* Topbit chars are printing chars */
extern uschar *process_info; /* For SIGUSR1 output */
extern int process_info_len;
extern uschar *process_log_path; /* Alternate path */
+extern const uschar *process_purpose; /* for debug output */
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
diff --git a/src/src/local_scan.h b/src/src/local_scan.h
index 206a843ec..b92be5628 100644
--- a/src/src/local_scan.h
+++ b/src/src/local_scan.h
@@ -31,6 +31,21 @@ settings, and the store functions. */
#include "store.h"
+/* Some people (Marc Merlin et al) are maintaining a patch that allows for
+dynamic local_scan() libraries. This code is not yet in Exim proper, but it
+helps the maintainers if we keep their ABI version numbers here. This may
+mutate into more general support later. The major number is increased when the
+ABI is changed in a non backward compatible way. The minor number is increased
+each time a new feature is added (in a way that doesn't break backward
+compatibility). */
+
+#define LOCAL_SCAN_ABI_VERSION_MAJOR 4
+#define LOCAL_SCAN_ABI_VERSION_MINOR 1
+#define LOCAL_SCAN_ABI_VERSION \
+ LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
+
+
+
/* The function and its return codes. */
extern int local_scan(int, uschar **);
@@ -99,19 +114,6 @@ the name of the data file to be present in the first line. */
#define SPOOL_DATA_START_OFFSET (MESSAGE_ID_LENGTH+3)
-/* Some people (Marc Merlin et al) are maintaining a patch that allows for
-dynamic local_scan() libraries. This code is not yet in Exim proper, but it
-helps the maintainers if we keep their ABI version numbers here. This may
-mutate into more general support later. The major number is increased when the
-ABI is changed in a non backward compatible way. The minor number is increased
-each time a new feature is added (in a way that doesn't break backward
-compatibility). */
-
-#define LOCAL_SCAN_ABI_VERSION_MAJOR 4
-#define LOCAL_SCAN_ABI_VERSION_MINOR 0
-#define LOCAL_SCAN_ABI_VERSION \
- LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
-
/* Structure definitions that are documented as visible in the function. */
typedef struct header_line {
@@ -179,9 +181,6 @@ extern BOOL smtp_input; /* TRUE if input is via SMTP */
/* Functions that are documented as visible in local_scan(). */
extern int child_close(pid_t, int);
-extern pid_t child_open(uschar **, uschar **, int, int *, int *, BOOL);
-extern pid_t child_open_exim(int *);
-extern pid_t child_open_exim2(int *, uschar *, uschar *);
extern void debug_printf(const char *, ...) PRINTF_FUNCTION(1,2);
extern uschar *expand_string(uschar *);
extern void header_add(int, const char *, ...);
@@ -223,10 +222,16 @@ with the original name. */
# define string_copy(s) string_copy_function(s)
# define string_copyn(s, n) string_copyn_function((s), (n))
# define string_copy_taint(s, t) string_copy_taint_function((s), (t))
+# define child_open_exim(p) child_open_exim_function((p), US"from local_scan")
+# define child_open_exim2(p, s, a) child_open_exim2_function((p), (s), (a), US"from local_scan")
+# define child_open(a,e,u,i,o,l) child_open_function((a),(e),(u),(i),(o),(l),US"from local_scan")
extern uschar * string_copy_function(const uschar *);
extern uschar * string_copyn_function(const uschar *, int n);
extern uschar * string_copy_taint_function(const uschar *, BOOL tainted);
+extern pid_t child_open_exim_function(int *, const uschar *);
+extern pid_t child_open_exim2_function(int *, uschar *, uschar *, const uschar *);
+extern pid_t child_open_function(uschar **, uschar **, int, int *, int *, BOOL, const uschar *);
#endif
/* End of local_scan.h */
diff --git a/src/src/log.c b/src/src/log.c
index e2543a74d..d9cf23a40 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -242,7 +242,7 @@ if (s1)
}
if (f.receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */
if (smtp_input) smtp_closedown(s2);
-exim_exit(EXIT_FAILURE, NULL);
+exim_exit(EXIT_FAILURE);
}
@@ -313,7 +313,7 @@ Returns: a file descriptor, or < 0 on failure (errno set)
int
log_create_as_exim(uschar *name)
{
-pid_t pid = fork();
+pid_t pid = exim_fork(US"logfile-create");
int status = 1;
int fd = -1;
@@ -510,7 +510,7 @@ non-setuid binary with log_arguments set, called in certain ways.) Rather than
just bombing out, force the log to stderr and carry on if stderr is available.
*/
-if (euid != root_uid && euid != exim_uid && log_stderr != NULL)
+if (euid != root_uid && euid != exim_uid && log_stderr)
{
*fd = fileno(log_stderr);
return;
@@ -519,7 +519,9 @@ if (euid != root_uid && euid != exim_uid && log_stderr != NULL)
/* Otherwise this is a disaster. This call is deliberately ONLY to the panic
log. If possible, save a copy of the original line that was being logged. If we
are recursing (can't open the panic log either), the pointer will already be
-set. */
+set. Also, when we had to use a subprocess for the create we didn't retrieve
+errno from it, so get the error from the open attempt above (which is often
+meaningful enough, so leave it). */
if (!panic_save_buffer)
if ((panic_save_buffer = US malloc(LOG_BUFFER_SIZE)))
@@ -765,7 +767,7 @@ if (!log_buffer)
if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
{
fprintf(stderr, "exim: failed to get store for log buffer\n");
- exim_exit(EXIT_FAILURE, NULL);
+ exim_exit(EXIT_FAILURE);
}
/* If we haven't already done so, inspect the setting of log_file_path to
@@ -981,7 +983,7 @@ if (!f.really_exim || f.log_testing_mode)
else
fprintf(log_stderr, "%s", CS log_buffer);
- if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE, US"");
+ if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE);
return;
}
diff --git a/src/src/moan.c b/src/src/moan.c
index 31d033c1a..48d4f905e 100644
--- a/src/src/moan.c
+++ b/src/src/moan.c
@@ -160,15 +160,16 @@ if ( ident == ERRMESS_DMARC_FORENSIC
&& (s2 = expand_string(string_sprintf("${address:%s}", s)))
&& *s2
)
- pid = child_open_exim2(&fd, s2, bounce_sender_authentication);
+ pid = child_open_exim2(&fd, s2, bounce_sender_authentication,
+ US"moan_send_message");
else
{
s = NULL;
- pid = child_open_exim(&fd);
+ pid = child_open_exim(&fd, US"moan_send_message");
}
#else
-pid = child_open_exim(&fd);
+pid = child_open_exim(&fd, US"moan_send_message");
#endif
if (pid < 0)
@@ -584,7 +585,7 @@ moan_tell_someone(uschar *who, address_item *addr,
FILE *f;
va_list ap;
int fd;
-int pid = child_open_exim(&fd);
+int pid = child_open_exim(&fd, US"moan_tell_someone");
if (pid < 0)
{
@@ -691,7 +692,7 @@ fprintf(stderr, "%d previous message%s successfully processed.\n",
fprintf(stderr, "The rest of the batch was abandoned.\n");
-exim_exit(yield, US"batch");
+exim_exit(yield);
}
@@ -820,7 +821,7 @@ if (!(s = expand_string(syntax_errors_to)))
/* If we can't create a process to send the message, just forget about
it. */
-pid = child_open_exim(&fd);
+pid = child_open_exim(&fd, US"moan_skipped_syntax_errors");
if (pid < 0)
{
diff --git a/src/src/queue.c b/src/src/queue.c
index 2d2772c1a..bb75c99cd 100644
--- a/src/src/queue.c
+++ b/src/src/queue.c
@@ -496,10 +496,8 @@ for (int i = queue_run_in_order ? -1 : 0;
}
else
for (i = 0; qpid[i]; ) i++;
- DEBUG(D_queue_run) debug_printf("q2stage forking\n");
- if ((qpid[i] = fork()))
+ if ((qpid[i] = exim_fork(US"qrun-phase-one")))
continue; /* parent loops around */
- DEBUG(D_queue_run) debug_printf("q2stage child\n");
}
/* Skip this message unless it's within the ID limits */
@@ -651,13 +649,13 @@ for (int i = queue_run_in_order ? -1 : 0;
#endif
single_item_retry:
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"qrun-delivery")) == 0)
{
int rc;
- testharness_pause_ms(100);
(void)close(pfd[pipe_read]);
rc = deliver_message(fq->text, force_delivery, FALSE);
- exim_underbar_exit(rc == DELIVER_NOT_ATTEMPTED, US"qrun-delivery");
+ exim_underbar_exit(rc == DELIVER_NOT_ATTEMPTED
+ ? EXIT_FAILURE : EXIT_SUCCESS);
}
if (pid < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork of delivery process from "
@@ -709,7 +707,7 @@ single_item_retry:
/* If initial of a 2-phase run, we are a child - so just exit */
if (f.queue_2stage && !queue_run_in_order)
- exim_exit(EXIT_SUCCESS, US"2-phase child");
+ exim_exit(EXIT_SUCCESS);
/* If we are in the test harness, and this is not the first of a 2-stage
queue run, update fudged queue times. */
@@ -726,7 +724,7 @@ single_item_retry:
go_around:
/* If initial of a 2-phase run, we are a child - so just exit */
if (f.queue_2stage && !queue_run_in_order)
- exim_exit(EXIT_SUCCESS, US"2-phase child");
+ exim_exit(EXIT_SUCCESS);
} /* End loop for list of messages */
tree_nonrecipients = NULL;
diff --git a/src/src/rda.c b/src/src/rda.c
index 547a8bf3b..0dc859107 100644
--- a/src/src/rda.c
+++ b/src/src/rda.c
@@ -615,7 +615,7 @@ with the parent process. */
oldsignal = signal(SIGCHLD, SIG_DFL);
search_tidyup();
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"router-interpret")) == 0)
{
header_line *waslast = header_last; /* Save last header */
@@ -768,7 +768,7 @@ if ((pid = fork()) == 0)
out:
(void)close(fd);
search_tidyup();
- exim_underbar_exit(0, US"rda");
+ exim_underbar_exit(EXIT_SUCCESS);
bad:
DEBUG(D_rewrite) debug_printf("rda_interpret: failed write to pipe\n");
diff --git a/src/src/readconf.c b/src/src/readconf.c
index a506d9f1d..1243e9082 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -3283,7 +3283,7 @@ while ((s = get_config_line()))
if (isupper(*s))
{
- if (!macro_read_assignment(s)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(s)) exim_exit(EXIT_FAILURE);
continue;
}
@@ -3719,7 +3719,7 @@ while ((buffer = get_config_line()))
(d->info->init)(d);
d = NULL;
}
- if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(buffer)) exim_exit(EXIT_FAILURE);
continue;
}
@@ -4232,7 +4232,7 @@ while(acl_line)
p = readconf_readname(name, sizeof(name), acl_line);
if (isupper(*name) && *p == '=')
{
- if (!macro_read_assignment(acl_line)) exim_exit(EXIT_FAILURE, US"");
+ if (!macro_read_assignment(acl_line)) exim_exit(EXIT_FAILURE);
acl_line = get_config_line();
continue;
}
diff --git a/src/src/receive.c b/src/src/receive.c
index 2745df6d1..0afb72b8c 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -216,7 +216,7 @@ if (STATVFS(CS path, &statbuf) != 0)
log_write(0, LOG_MAIN|LOG_PANIC, "cannot accept message: failed to stat "
"%s directory %s: %s", name, path, strerror(errno));
smtp_closedown(US"spool or log directory problem");
- exim_exit(EXIT_FAILURE, NULL);
+ exim_exit(EXIT_FAILURE);
}
*inodeptr = (statbuf.F_FILES > 0)? statbuf.F_FAVAIL : -1;
@@ -372,7 +372,7 @@ if (!already_bombing_out)
/* Exit from the program (non-BSMTP cases) */
-exim_exit(EXIT_FAILURE, NULL);
+exim_exit(EXIT_FAILURE);
}
@@ -1172,7 +1172,7 @@ if (error_handling == ERRORS_SENDER)
else
fprintf(stderr, "exim: %s%s\n", text2, text1); /* Sic */
(void)fclose(f);
-exim_exit(error_rc, US"");
+exim_exit(error_rc);
}
@@ -3340,7 +3340,7 @@ if (extract_recip && (bad_addresses || recipients_count == 0))
{
Uunlink(spool_name);
(void)fclose(spool_data_file);
- exim_exit(error_rc, US"receiving");
+ exim_exit(error_rc);
}
}
diff --git a/src/src/route.c b/src/src/route.c
index fd3cb3e64..c7833ebb4 100644
--- a/src/src/route.c
+++ b/src/src/route.c
@@ -736,7 +736,7 @@ while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))))
otherwise. Save the old state for resetting on the wait. */
oldsignal = signal(SIGCHLD, SIG_DFL);
- pid = fork();
+ pid = exim_fork(US"require-files");
/* If fork() fails, reinstate the original error and behave as if
this block of code were not present. This is the same behaviour as happens
@@ -759,9 +759,9 @@ while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))))
exim_setugid(uid, gid, TRUE,
string_sprintf("require_files check, file=%s", ss));
if (route_check_access(ss, uid, gid, 4))
- exim_underbar_exit(0, US"route-check-access");
+ exim_underbar_exit(EXIT_SUCCESS);
DEBUG(D_route) debug_printf("route_check_access() failed\n");
- exim_underbar_exit(1, US"route-check-access");
+ exim_underbar_exit(EXIT_FAILURE);
}
/* In the parent, wait for the child to finish */
diff --git a/src/src/routers/queryprogram.c b/src/src/routers/queryprogram.c
index 107632f44..767dc7167 100644
--- a/src/src/routers/queryprogram.c
+++ b/src/src/routers/queryprogram.c
@@ -308,10 +308,8 @@ if (!transport_set_up_command(&argvptr, /* anchor for arg list */
/* Create the child process, making it a group leader. */
-pid = child_open_uid(argvptr, NULL, 0077, puid, pgid, &fd_in, &fd_out,
- current_directory, TRUE);
-
-if (pid < 0)
+if ((pid = child_open_uid(argvptr, NULL, 0077, puid, pgid, &fd_in, &fd_out,
+ current_directory, TRUE, US"queryprogram-cmd")) < 0)
{
addr->message = string_sprintf("%s router couldn't create child process: %s",
rblock->name, strerror(errno));
diff --git a/src/src/sieve.c b/src/src/sieve.c
index 286be789a..446766534 100644
--- a/src/src/sieve.c
+++ b/src/src/sieve.c
@@ -3084,7 +3084,8 @@ while (*filter->pc)
{
int pid, fd;
- if ((pid = child_open_exim2(&fd,envelope_from,envelope_from))>=1)
+ if ((pid = child_open_exim2(&fd, envelope_from, envelope_from,
+ US"sieve-notify")) >= 1)
{
FILE *f;
uschar *buffer;
@@ -3092,7 +3093,8 @@ while (*filter->pc)
f = fdopen(fd, "wb");
fprintf(f,"From: %s\n", from.length == -1
- ? expand_string(US"$local_part_prefix$local_part$local_part_suffix@$domain") : from.character);
+ ? expand_string(US"$local_part_prefix$local_part$local_part_suffix@$domain")
+ : from.character);
for (string_item * p = recipient; p; p=p->next)
fprintf(f,"To: %s\n",p->text);
fprintf(f,"Auto-Submitted: auto-notified; %s\n",filter->enotify_mailto_owner);
@@ -3103,9 +3105,11 @@ while (*filter->pc)
message.length=Ustrlen(message.character);
}
/* Allocation is larger than necessary, but enough even for split MIME words */
- buffer_capacity=32+4*message.length;
+ buffer_capacity = 32 + 4*message.length;
buffer=store_get(buffer_capacity, TRUE);
- if (message.length!=-1) fprintf(f,"Subject: %s\n",parse_quote_2047(message.character, message.length, US"utf-8", buffer, buffer_capacity, TRUE));
+ if (message.length != -1)
+ fprintf(f, "Subject: %s\n", parse_quote_2047(message.character,
+ message.length, US"utf-8", buffer, buffer_capacity, TRUE));
fprintf(f,"\n");
if (body.length>0) fprintf(f,"%s\n",body.character);
fflush(f);
@@ -3113,27 +3117,17 @@ while (*filter->pc)
(void)child_close(pid, 0);
}
}
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Notification to `%s': '%s'.\n",method.character,message.length!=-1 ? message.character : CUS "");
- }
#endif
}
else
- {
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Repeated notification to `%s' ignored.\n",method.character);
- }
- }
}
else
- {
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Ignoring notification, triggering message contains Auto-submitted: field.\n");
- }
- }
}
}
#endif
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 66f752dd4..9055020e1 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -457,7 +457,7 @@ if (smtp_batched_input)
smtp_notquit_exit(US"command-timeout", US"421",
US"%s: SMTP command timeout - closing connection",
smtp_active_hostname);
-exim_exit(EXIT_FAILURE, US"receiving");
+exim_exit(EXIT_FAILURE);
}
void
@@ -468,7 +468,7 @@ if (smtp_batched_input)
moan_smtp_batch(NULL, "421 SIGTERM received"); /* Does not return */
smtp_notquit_exit(US"signal-exit", US"421",
US"%s: Service not available - closing connection", smtp_active_hostname);
-exim_exit(EXIT_FAILURE, US"receiving");
+exim_exit(EXIT_FAILURE);
}
void
@@ -931,7 +931,7 @@ if (!yield)
{
log_write(0, LOG_MAIN|LOG_PANIC, "string too large in smtp_printf()");
smtp_closedown(US"Unexpected error");
- exim_exit(EXIT_FAILURE, NULL);
+ exim_exit(EXIT_FAILURE);
}
/* If this is the first output for a (non-batch) RCPT command, see if all RCPTs
@@ -5759,7 +5759,7 @@ while (done <= 0)
oldsignal = signal(SIGCHLD, SIG_IGN);
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"etrn-command")) == 0)
{
smtp_input = FALSE; /* This process is not associated with the */
(void)fclose(smtp_in); /* SMTP call any more. */
@@ -5770,7 +5770,8 @@ while (done <= 0)
/* If not serializing, do the exec right away. Otherwise, fork down
into another process. */
- if (!smtp_etrn_serialize || (pid = fork()) == 0)
+ if ( !smtp_etrn_serialize
+ || (pid = exim_fork(US"etrn-serialised-command")) == 0)
{
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{in,out,err} exist */
@@ -5799,7 +5800,7 @@ while (done <= 0)
}
enq_end(etrn_serialize_key);
- exim_underbar_exit(EXIT_SUCCESS, US"etrn-serialize-interproc");
+ exim_underbar_exit(EXIT_SUCCESS);
}
/* Back in the top level SMTP process. Check that we started a subprocess
diff --git a/src/src/tls.c b/src/src/tls.c
index a0cfcbf25..1362032f3 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -441,7 +441,7 @@ else if (!nowarn && !tls_certificate)
oldsignal = signal(SIGCHLD, SIG_DFL);
fflush(NULL);
-if ((pid = fork()) < 0)
+if ((pid = exim_fork(US"cipher-validate")) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
if (pid == 0)
@@ -455,7 +455,7 @@ if (pid == 0)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"tls_require_ciphers invalid: %s", errmsg);
fflush(NULL);
- exim_underbar_exit(0, NULL);
+ exim_underbar_exit(EXIT_SUCCESS);
}
do {
diff --git a/src/src/transport.c b/src/src/transport.c
index e4aaa7deb..aca7c7f5a 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -1189,7 +1189,8 @@ transport_write_message(transport_ctx * tctx, int size_limit)
{
BOOL last_filter_was_NL = TRUE;
BOOL save_spool_file_wireformat = f.spool_file_wireformat;
-int rc, len, yield, fd_read, fd_write, save_errno;
+BOOL yield;
+int rc, len, fd_read, fd_write, save_errno;
int pfd[2] = {-1, -1};
pid_t filter_pid, write_pid;
@@ -1233,10 +1234,10 @@ write_pid = (pid_t)(-1);
{
int bits = fcntl(tctx->u.fd, F_GETFD);
- (void)fcntl(tctx->u.fd, F_SETFD, bits | FD_CLOEXEC);
+ (void) fcntl(tctx->u.fd, F_SETFD, bits | FD_CLOEXEC);
filter_pid = child_open(USS transport_filter_argv, NULL, 077,
- &fd_write, &fd_read, FALSE);
- (void)fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
+ &fd_write, &fd_read, FALSE, US"transport-filter");
+ (void) fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
}
if (filter_pid < 0) goto TIDY_UP; /* errno set */
@@ -1249,7 +1250,7 @@ via a(nother) pipe. While writing to the filter, we do not do the CRLF,
smtp dots, or check string processing. */
if (pipe(pfd) != 0) goto TIDY_UP; /* errno set */
-if ((write_pid = fork()) == 0)
+if ((write_pid = exim_fork(US"tpt-filter-writer")) == 0)
{
BOOL rc;
(void)close(fd_read);
@@ -1273,7 +1274,7 @@ if ((write_pid = fork()) == 0)
!= sizeof(struct timeval)
)
rc = FALSE; /* compiler quietening */
- exim_underbar_exit(0, US"tpt-filter");
+ exim_underbar_exit(EXIT_SUCCESS);
}
save_errno = errno;
@@ -1321,6 +1322,7 @@ for (;;)
ALARM_CLR(0);
if (sigalrm_seen)
{
+ DEBUG(D_transport) debug_printf("timed out reading from filter\n");
errno = ETIMEDOUT;
f.transport_filter_timed_out = TRUE;
goto TIDY_UP;
@@ -1439,7 +1441,7 @@ DEBUG(D_transport)
{
debug_printf("end of filtering transport writing: yield=%d\n", yield);
if (!yield)
- debug_printf("errno=%d more_errno=%d\n", errno, tctx->addr->more_errno);
+ debug_printf(" errno=%d more_errno=%d\n", errno, tctx->addr->more_errno);
}
return yield;
@@ -1732,6 +1734,7 @@ while (1)
}
/* first thing remove current message id if it exists */
+ /*XXX but what if it has un-sent addrs? */
for (i = 0; i < msgq_count; ++i)
if (Ustrcmp(msgq[i].message_id, message_id) == 0)
@@ -1955,18 +1958,15 @@ int status;
DEBUG(D_transport) debug_printf("transport_pass_socket entered\n");
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"continued-transport-interproc")) == 0)
{
/* Disconnect entirely from the parent process. If we are running in the
test harness, wait for a bit to allow the previous process time to finish,
write the log, etc., so that the output is always in the same order for
automatic comparison. */
- if ((pid = fork()) != 0)
- {
- DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (final-pid %d)\n", pid);
+ if ((pid = exim_fork(US"continued-transport")) != 0)
_exit(EXIT_SUCCESS);
- }
testharness_pause_ms(1000);
transport_do_pass_socket(transport_name, hostname, hostaddress,
@@ -1981,7 +1981,6 @@ if (pid > 0)
{
int rc;
while ((rc = wait(&status)) != pid && (rc >= 0 || errno != ECHILD));
- DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (inter-pid %d)\n", pid);
return TRUE;
}
else
diff --git a/src/src/transports/autoreply.c b/src/src/transports/autoreply.c
index e75349ed9..90a5aa4be 100644
--- a/src/src/transports/autoreply.c
+++ b/src/src/transports/autoreply.c
@@ -567,12 +567,10 @@ if (file)
/* Make a subprocess to send the message */
-pid = child_open_exim(&fd);
-
-/* Creation of child failed; defer this delivery. */
-
-if (pid < 0)
+if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
{
+ /* Creation of child failed; defer this delivery. */
+
addr->transport_return = DEFER;
addr->basic_errno = errno;
addr->message = string_sprintf("Failed to create child process to send "
diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c
index 32c57166c..517a13494 100644
--- a/src/src/transports/lmtp.c
+++ b/src/src/transports/lmtp.c
@@ -500,7 +500,8 @@ if (ob->cmd)
uid/gid and current directory. Request that the new process be a process group
leader, so we can kill it and all its children on an error. */
- if ((pid = child_open(USS argv, NULL, 0, &fd_in, &fd_out, TRUE)) < 0)
+ if ((pid = child_open(USS argv, NULL, 0, &fd_in, &fd_out, TRUE,
+ US"lmtp-tpt-cmd")) < 0)
{
addrlist->message = string_sprintf(
"Failed to create child process for %s transport: %s", tblock->name,
@@ -514,8 +515,7 @@ leader, so we can kill it and all its children on an error. */
else
{
DEBUG(D_transport) debug_printf("using socket %s\n", ob->skt);
- sockname = expand_string(ob->skt);
- if (sockname == NULL)
+ if (!(sockname = expand_string(ob->skt)))
{
addrlist->message = string_sprintf("Expansion of \"%s\" (socket setting "
"for %s transport) failed: %s", ob->skt, tblock->name,
diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c
index ca22f2659..6a7f150ac 100644
--- a/src/src/transports/pipe.c
+++ b/src/src/transports/pipe.c
@@ -725,7 +725,8 @@ reading of the output pipe. */
uid/gid and current directory. Request that the new process be a process group
leader, so we can kill it and all its children on a timeout. */
-if ((pid = child_open(USS argv, envp, ob->umask, &fd_in, &fd_out, TRUE)) < 0)
+if ((pid = child_open(USS argv, envp, ob->umask, &fd_in, &fd_out, TRUE,
+ US"pipe-tpt-cmd")) < 0)
{
addr->transport_return = DEFER;
addr->message = string_sprintf(
@@ -737,7 +738,7 @@ tctx.u.fd = fd_in;
/* Now fork a process to handle the output that comes down the pipe. */
-if ((outpid = fork()) < 0)
+if ((outpid = exim_fork(US"pipe-tpt-output")) < 0)
{
addr->basic_errno = errno;
addr->transport_return = DEFER;
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 6f999097a..fc5bb7801 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1685,7 +1685,7 @@ current_local_identity =
smtp_local_identity(s_compare->current_sender_address, s_compare->tblock);
if (!(new_sender_address = deliver_get_sender_address(message_id)))
- return 0;
+ return FALSE;
message_local_identity =
smtp_local_identity(new_sender_address, s_compare->tblock);
@@ -3284,13 +3284,9 @@ int max_fd = MAX(pfd[0], tls_out.active.sock) + 1;
int rc, i;
close(pfd[1]);
-if ((rc = fork()))
- {
- DEBUG(D_transport) debug_printf("proxy-proc final-pid %d\n", rc);
+if ((rc = exim_fork(US"tls-proxy")))
_exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
- }
-testharness_pause_ms(100); /* let parent debug out */
set_process_info("proxying TLS connection for continued transport");
FD_ZERO(&rfds);
FD_SET(tls_out.active.sock, &rfds);
@@ -3365,7 +3361,7 @@ for (int fd_bits = 3; fd_bits; )
done:
testharness_pause_ms(100); /* let logging complete */
- exim_exit(0, US"TLS proxy");
+ exim_exit(EXIT_SUCCESS);
}
#endif
@@ -3459,7 +3455,7 @@ if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
}
/* If there is a filter command specified for this transport, we can now
-set it up. This cannot be done until the identify of the host is known. */
+set it up. This cannot be done until the identity of the host is known. */
if (tblock->filter_command)
{
@@ -4279,10 +4275,9 @@ propagate it from the initial
#ifndef DISABLE_TLS
if (tls_out.active.sock >= 0)
{
- int pid = fork();
+ int pid = exim_fork(US"tls-proxy-interproc");
if (pid == 0) /* child; fork again to disconnect totally */
{
- testharness_pause_ms(100); /* let parent debug out */
/* does not return */
smtp_proxy_tls(sx->cctx.tls_ctx, sx->buffer, sizeof(sx->buffer), pfd,
ob->command_timeout);
@@ -4290,7 +4285,6 @@ propagate it from the initial
if (pid > 0) /* parent */
{
- DEBUG(D_transport) debug_printf("proxy-proc inter-pid %d\n", pid);
close(pfd[0]);
/* tidy the inter-proc to disconn the proxy proc */
waitpid(pid, NULL, 0);