X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/691ca88ca06899e02e77cb28fbf075de450607bc..4b01271fa595a08e68ba8c58d6404e83623aa9c8:/src/src/queue.c diff --git a/src/src/queue.c b/src/src/queue.c index 1b70c02b6..9dbf3e717 100644 --- a/src/src/queue.c +++ b/src/src/queue.c @@ -353,6 +353,7 @@ uschar *log_detail = NULL; int subcount = 0; uschar subdirs[64]; pid_t qpid[4] = {0}; /* Parallelism factor for q2stage 1st phase */ +BOOL single_id = FALSE; #ifdef MEASURE_TIMING report_time_since(×tamp_startup, US"queue_run start"); @@ -405,6 +406,9 @@ if (!recurse) queue_name, log_detail); else log_write(L_queue_run, LOG_MAIN, "Start queue run: %s", log_detail); + + single_id = start_id && stop_id && !f.queue_2stage + && Ustrcmp(start_id, stop_id) == 0; } /* If deliver_selectstring is a regex, compile it. */ @@ -492,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 */ @@ -646,13 +648,13 @@ for (int i = queue_run_in_order ? -1 : 0; report_time_since(×tamp_startup, US"queue msg selected"); #endif - if ((pid = fork()) == 0) +single_item_retry: + 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); + exim_underbar_exit(rc == DELIVER_NOT_ATTEMPTED, US"qrun-delivery"); } if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork of delivery process from " @@ -677,6 +679,18 @@ for (int i = queue_run_in_order ? -1 : 0; "queue run: process %d crashed with signal %d while delivering %s", (int)pid, status & 0x00ff, fq->text); + /* If single-item delivery was untried (likely due to locking) + retry once after a delay */ + + if (status & 0xff00 && single_id) + { + single_id = FALSE; + DEBUG(D_queue_run) debug_printf("qrun single-item pause before retry\n"); + millisleep(500); + DEBUG(D_queue_run) debug_printf("qrun single-item retry after pause\n"); + goto single_item_retry; + } + /* Before continuing, wait till the pipe gets closed at the far end. This tells us that any children created by the delivery to re-use any SMTP channels have all finished. Since no process actually writes to the pipe,