X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/18eacc1185bea956bd9c793ab34e582c08941799..HEAD:/src/src/queue.c diff --git a/src/src/queue.c b/src/src/queue.c index fa4fc0aec..57e5eb769 100644 --- a/src/src/queue.c +++ b/src/src/queue.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) The Exim Maintainers 2020 - 2022 */ +/* Copyright (c) The Exim Maintainers 2020 - 2024 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ @@ -341,8 +341,10 @@ so force the first one. The selecting string can optionally be a regex, or refer to the sender instead of recipients. If queue_2stage is set, the queue is scanned twice. The first time, queue_smtp -is set so that routing is done for all messages. Thus in the second run those -that are routed to the same host should go down the same SMTP connection. +is set so that routing is done for all messages. A call of the transport adds +each message_id in turn to a list for the resulting host. +Then in the second run those that are routed to the same host should all go down +a single SMTP connection. Arguments: q queue-runner descriptor @@ -354,13 +356,13 @@ Returns: nothing */ void -queue_run(qrunner * q, uschar * start_id, uschar * stop_id, BOOL recurse) +queue_run(qrunner * q, const uschar * start_id, const uschar * stop_id, BOOL recurse) { BOOL force_delivery = q->queue_run_force || deliver_selectstring || deliver_selectstring_sender; -const pcre2_code *selectstring_regex = NULL; -const pcre2_code *selectstring_regex_sender = NULL; -uschar *log_detail = NULL; +const pcre2_code * selectstring_regex = NULL; +const pcre2_code * selectstring_regex_sender = NULL; +uschar * log_detail = NULL; int subcount = 0; uschar subdirs[64]; pid_t qpid[4] = {0}; /* Parallelism factor for q2stage 1st phase */ @@ -394,20 +396,19 @@ f.queue_running = TRUE; if (!recurse) { - uschar extras[8]; - uschar *p = extras; + uschar extras[8], * p = extras; if (q->queue_2stage) *p++ = 'q'; if (q->queue_run_first_delivery) *p++ = 'i'; if (q->queue_run_force) *p++ = 'f'; if (q->deliver_force_thaw) *p++ = 'f'; if (q->queue_run_local) *p++ = 'l'; - *p = 0; + *p = '\0'; p = big_buffer; p += sprintf(CS p, "pid=%d", (int)queue_run_pid); - if (extras[0] != 0) + if (*extras) p += sprintf(CS p, " -q%s", extras); if (deliver_selectstring) @@ -444,6 +445,15 @@ if (deliver_selectstring_sender && f.deliver_selectstring_sender_regex) selectstring_regex_sender = regex_must_compile(deliver_selectstring_sender, MCS_CASELESS, FALSE); +#ifndef DISABLE_TLS +if (!queue_tls_init) + { + queue_tls_init = TRUE; + /* Preload TLS library info for smtp transports. */ + tls_client_creds_reload(FALSE); + } +#endif + /* If the spool is split into subdirectories, we want to process it one directory at a time, so as to spread out the directory scanning and the delivering when there are lots of messages involved, except when @@ -503,23 +513,31 @@ for (int i = queue_run_in_order ? -1 : 0; (double)load_average/1000.0, (double)deliver_queue_load_max/1000.0); - /* If initial of a 2-phase run, maintain a set of child procs - to get disk parallelism */ + /* If initial of a 2-phase run (and not under the test-harness) + maintain a set of child procs to get disk parallelism */ if (q->queue_2stage && !queue_run_in_order) { int i; - if (qpid[f.running_in_test_harness ? 0 : nelem(qpid) - 1]) - { - DEBUG(D_queue_run) debug_printf("q2stage waiting for child %d\n", (int)qpid[0]); + if (qpid[ +#ifndef MEASURE_TIMING + f.running_in_test_harness ? 0 : +#endif + nelem(qpid) - 1]) + { /* The child table is maxed out; wait for the oldest */ + DEBUG(D_queue_run) + debug_printf("q2stage waiting for child %d\n", (int)qpid[0]); waitpid(qpid[0], NULL, 0); - DEBUG(D_queue_run) debug_printf("q2stage reaped child %d\n", (int)qpid[0]); - if (f.running_in_test_harness) i = 0; - else for (i = 0; i < nelem(qpid) - 1; i++) qpid[i] = qpid[i+1]; + DEBUG(D_queue_run) + debug_printf("q2stage reaped child %d\n", (int)qpid[0]); +#ifndef MEASURE_TIMING + if (f.running_in_test_harness) i = 0; else +#endif + for (i = 0; i < nelem(qpid) - 1; i++) qpid[i] = qpid[i+1]; qpid[i] = 0; } else - for (i = 0; qpid[i]; ) i++; + for (i = 0; qpid[i]; ) i++; /* find first spare slot */ if ((qpid[i] = exim_fork(US"qrun-phase-one"))) continue; /* parent loops around */ } @@ -555,7 +573,8 @@ for (int i = queue_run_in_order ? -1 : 0; follow. If the message is chosen for delivery, the header is read again in the deliver_message() function, in a subprocess. */ - if (spool_read_header(fq->text, FALSE, TRUE) != spool_read_OK) goto go_around; + if (spool_read_header(fq->text, FALSE, TRUE) != spool_read_OK) + goto go_around; f.dont_deliver = orig_dont_deliver; /* Now decide if we want to deliver this message. As we have read the @@ -585,7 +604,7 @@ for (int i = queue_run_in_order ? -1 : 0; else if ( deliver_selectstring_sender && !(f.deliver_selectstring_sender_regex ? regex_match(selectstring_regex_sender, sender_address, -1, NULL) - : (strstric(sender_address, deliver_selectstring_sender, FALSE) + : (strstric_c(sender_address, deliver_selectstring_sender, FALSE) != NULL) ) ) { @@ -601,10 +620,10 @@ for (int i = queue_run_in_order ? -1 : 0; int i; for (i = 0; i < recipients_count; i++) { - uschar *address = recipients_list[i].address; + const uschar * address = recipients_list[i].address; if ( (f.deliver_selectstring_regex ? regex_match(selectstring_regex, address, -1, NULL) - : (strstric(address, deliver_selectstring, FALSE) != NULL) + : (strstric_c(address, deliver_selectstring, FALSE) != NULL) ) && tree_search(tree_nonrecipients, address) == NULL ) @@ -664,23 +683,15 @@ for (int i = queue_run_in_order ? -1 : 0; name. The return of the process is zero if a delivery was attempted. */ fq->text[Ustrlen(fq->text)-2] = 0; - set_process_info("running queue: %s", fq->text); + set_process_info("running queue%s: %s", + q->queue_2stage ? "(ph 1)" : "", fq->text); #ifdef MEASURE_TIMING report_time_since(×tamp_startup, US"queue msg selected"); #endif -#ifndef DISABLE_TLS - if (!queue_tls_init) - { - queue_tls_init = TRUE; - /* Preload TLS library info for smtp transports. Once, and only if we - have a delivery to do. */ - tls_client_creds_reload(FALSE); - } -#endif - single_item_retry: - if ((pid = exim_fork(US"qrun-delivery")) == 0) + if ((pid = exim_fork( + q->queue_2stage ? US"qrun-p1-delivery" : US"qrun-delivery")) == 0) { int rc; (void)close(pfd[pipe_read]); @@ -737,6 +748,7 @@ single_item_retry: set_process_info("running queue"); /* If initial of a 2-phase run, we are a child - so just exit */ + if (q->queue_2stage && !queue_run_in_order) exim_exit(EXIT_SUCCESS); @@ -794,9 +806,10 @@ if (q->queue_2stage) else break; #ifdef MEASURE_TIMING - report_time_since(×tamp_startup, US"queue_run 1st phase done"); + report_time_since(×tamp_startup, US"queue_run phase 1 done"); #endif q->queue_2stage = f.queue_2stage = FALSE; + DEBUG(D_queue_run) debug_printf("queue_run phase 2 start\n"); queue_run(q, start_id, stop_id, TRUE); } @@ -813,7 +826,7 @@ if (!recurse) void -single_queue_run(qrunner * q, uschar * start_id, uschar * stop_id) +single_queue_run(qrunner * q, const uschar * start_id, const uschar * stop_id) { DEBUG(D_queue_run) debug_printf("Single queue run%s%s%s%s\n", start_id ? US" starting at " : US"", @@ -919,7 +932,7 @@ Returns: nothing */ void -queue_list(int option, uschar ** list, int count) +queue_list(int option, const uschar ** list, int count) { int subcount; int now = (int)time(NULL); @@ -961,7 +974,9 @@ each time. */ if (option == QL_MSGID_ONLY) /* Print only the message IDs from the chain */ for (; qf; qf = qf->next) - fprintf(stdout, "%.*s\n", MESSAGE_ID_LENGTH, qf->text); + fprintf(stdout, "%.*s\n", + is_old_message_id(qf->text) ? MESSAGE_ID_LENGTH_OLD : MESSAGE_ID_LENGTH, + qf->text); else for (; qf && (reset_point = store_mark()); @@ -1021,7 +1036,9 @@ else for (; } fprintf(stdout, "%s %.*s", - string_format_size(size, big_buffer), MESSAGE_ID_LENGTH, qf->text); + string_format_size(size, big_buffer), + is_old_message_id(qf->text) ? MESSAGE_ID_LENGTH_OLD : MESSAGE_ID_LENGTH, + qf->text); if (env_read && sender_address) { @@ -1093,7 +1110,7 @@ Returns: FALSE if there was any problem */ BOOL -queue_action(uschar * id, int action, uschar ** argv, int argc, +queue_action(const uschar * id, int action, const uschar ** argv, int argc, int recipients_arg) { BOOL yield = TRUE; @@ -1369,9 +1386,10 @@ switch(action) tree_search(tree_nonrecipients, recipients_list[i].address); if (!delivered) { - uschar * save_local = deliver_localpart; + const uschar * save_local = deliver_localpart; const uschar * save_domain = deliver_domain; - uschar * addr = recipients_list[i].address, * errmsg = NULL; + const uschar * addr = recipients_list[i].address; + uschar * errmsg = NULL; int start, end, dom; if (!parse_extract_address(addr, &errmsg, &start, &end, &dom, TRUE)) @@ -1614,3 +1632,5 @@ else DEBUG(D_queue_run) debug_printf(" socket: %s\n", strerror(errno)); #endif /*!COMPILE_UTILITY*/ /* End of queue.c */ +/* vi: aw ai sw=2 +*/