From 8e9fdd6369f0a7a81f0ca195e24edd372f7ca3ef Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 15 Mar 2020 17:34:02 +0000 Subject: [PATCH] labelled-process fork function --- src/src/child.c | 14 +++++++++----- src/src/daemon.c | 10 +++++----- src/src/deliver.c | 14 +++++++------- src/src/exim.c | 4 ++-- src/src/functions.h | 18 ++++++++++++++++++ src/src/globals.c | 1 + src/src/globals.h | 1 + src/src/local_scan.h | 34 +++++++++++++++++++--------------- src/src/log.c | 2 +- src/src/moan.c | 11 ++++++----- src/src/queue.c | 4 ++-- src/src/rda.c | 2 +- src/src/route.c | 2 +- src/src/sieve.c | 28 +++++++++++----------------- src/src/smtp_in.c | 5 +++-- src/src/tls.c | 2 +- src/src/transport.c | 6 +++--- src/src/transports/autoreply.c | 8 +++----- src/src/transports/pipe.c | 2 +- src/src/transports/smtp.c | 4 ++-- 20 files changed, 97 insertions(+), 75 deletions(-) diff --git a/src/src/child.c b/src/src/child.c index c5054b6fb..f6d44e1b1 100644 --- a/src/src/child.c +++ b/src/src/child.c @@ -185,13 +185,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 +204,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 +224,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 @@ -337,7 +341,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(US"queryprogram"); /* queryprogram tpt is sole caller */ /* 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 diff --git a/src/src/daemon.c b/src/src/daemon.c index aa36a5dc9..a1ef1f930 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 */ @@ -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); @@ -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, @@ -1601,7 +1601,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 */ @@ -2130,7 +2130,7 @@ for (;;) 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()); diff --git a/src/src/deliver.c b/src/src/deliver.c index 5c5167b3a..5d825cd66 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"warning message")) > 0) { FILE *f = fdopen(fd, "wb"); if (errors_reply_to && !contains_header(US"Reply-To", warn_message)) @@ -4647,7 +4647,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; @@ -7336,7 +7336,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 +7537,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)); @@ -8195,7 +8195,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,7 +8583,7 @@ if (cutthrough.cctx.sock >= 0 && cutthrough.callout_hold_only) goto fail; where = US"fork"; - if ((pid = fork()) < 0) + if ((pid = exim_fork(US"tls-proxy interproc")) < 0) goto fail; else if (pid == 0) /* child: fork again to totally disconnect */ diff --git a/src/src/exim.c b/src/src/exim.c index 4e4b6bb75..6bde8fd96 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -4608,7 +4608,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, US"cmdline-delivery"); @@ -5694,7 +5694,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 */ diff --git a/src/src/functions.h b/src/src/functions.h index 042006f95..9e71d0c20 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -150,6 +150,9 @@ 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_uid(const uschar **, const uschar **, int, uid_t *, gid_t *, int *, int *, uschar *, BOOL); extern BOOL cleanup_environment(void); @@ -1108,6 +1111,21 @@ errno = EACCES; return NULL; } +/******************************************************************************/ +/* Process manipulation */ + +static inline pid_t +exim_fork(const unsigned char * purpose) +{ +pid_t pid = fork(); +if (pid == 0) process_purpose = purpose; +return pid; +} + +#define child_open_exim(p, r) child_open_exim_function((p), (r)) +#define child_open_exim2(p, s, a, r) child_open_exim2_function((p), (s), (a), (r)) + +/******************************************************************************/ #endif /* !MACRO_PREDEF */ #endif /* _FUNCTIONS_H_ */ diff --git a/src/src/globals.c b/src/src/globals.c index a771f1193..28e78d4d6 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..bb131d380 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 { @@ -180,8 +182,6 @@ extern BOOL smtp_input; /* TRUE if input is via SMTP */ 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 +223,14 @@ 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") 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 *); #endif /* End of local_scan.h */ diff --git a/src/src/log.c b/src/src/log.c index e2543a74d..e80c17757 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -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; diff --git a/src/src/moan.c b/src/src/moan.c index 31d033c1a..51f5da58a 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) { @@ -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 c9ac84be6..2b64f5229 100644 --- a/src/src/queue.c +++ b/src/src/queue.c @@ -497,7 +497,7 @@ 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"); } @@ -651,7 +651,7 @@ 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); diff --git a/src/src/rda.c b/src/src/rda.c index 547a8bf3b..85791c2f7 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 */ diff --git a/src/src/route.c b/src/src/route.c index fd3cb3e64..6226b0685 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 diff --git a/src/src/sieve.c b/src/src/sieve.c index 5e8d1e6f4..e07b7da18 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..b5f44f548 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -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 */ diff --git a/src/src/tls.c b/src/src/tls.c index a0cfcbf25..2f9faa3c7 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) diff --git a/src/src/transport.c b/src/src/transport.c index 3eb1c8097..d92ad4c37 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -1248,7 +1248,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"transport filter")) == 0) { BOOL rc; (void)close(fd_read); @@ -1954,14 +1954,14 @@ 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) + if ((pid = exim_fork(US"continued-transport")) != 0) { DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (final-pid %d)\n", pid); _exit(EXIT_SUCCESS); diff --git a/src/src/transports/autoreply.c b/src/src/transports/autoreply.c index 4b5ef8e17..2b487b435 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/pipe.c b/src/src/transports/pipe.c index ca22f2659..83272d80a 100644 --- a/src/src/transports/pipe.c +++ b/src/src/transports/pipe.c @@ -737,7 +737,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-transport 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..459110b80 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -3284,7 +3284,7 @@ int max_fd = MAX(pfd[0], tls_out.active.sock) + 1; int rc, i; close(pfd[1]); -if ((rc = fork())) +if ((rc = exim_fork(US"tls proxy"))) { DEBUG(D_transport) debug_printf("proxy-proc final-pid %d\n", rc); _exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS); @@ -4279,7 +4279,7 @@ 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 */ -- 2.30.2