Implement freeze_signal on pipe transport.
authorPhil Pennock <pdp@exim.org>
Sun, 13 Feb 2011 05:09:18 +0000 (00:09 -0500)
committerPhil Pennock <pdp@exim.org>
Sun, 13 Feb 2011 05:09:18 +0000 (00:09 -0500)
Patch from Jakob Hirsch.

fixes bug 1042

doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/transports/pipe.c
src/src/transports/pipe.h

index 9dacb979c5d012dd59a911a89281bd1e32010339..b75e36ba4ba6540491ea1a3211b6db1f27fc4d63 100644 (file)
@@ -21033,9 +21033,14 @@ later"&. In this case, delivery is deferred. Details of a permanent failure are
 logged, but are not included in the bounce message, which merely contains
 &"local delivery failed"&.
 
+If the command exits on a signal and the &%freeze_signal%& option is set then
+the message will be frozen in the queue. If that option is not set, a bounce
+will be sent as normal.
+
 If the return code is greater than 128 and the command being run is a shell
 script, it normally means that the script was terminated by a signal whose
-value is the return code minus 128.
+value is the return code minus 128. The &%freeze_signal%& option does not
+apply in this case.
 
 If Exim is unable to run the command (that is, if &[execve()]& fails), the
 return code is set to 127. This is the value that a shell returns if it is
@@ -21244,6 +21249,16 @@ is set, failure to exec is treated specially, and causes the message to be
 frozen, whatever the setting of &%ignore_status%&.
 
 
+.new
+.otion freeze_signal pipe boolean false
+.cindex "signal exit"
+.cidenx "&(pipe)& transport", "signal exit"
+Normally if the process run by a command in a pipe transport exits on a signal,
+a bounce message is sent. If &%freeze_signal%& is set, the message will be
+frozen in Exim's queue instead.
+.wen
+
+
 .option ignore_status pipe boolean false
 If this option is true, the status returned by the subprocess that is set up to
 run the command is ignored, and Exim behaves as if zero had been returned.
index 5d636a74d7acdc11012f59e418a17232ca316e62..7aeba3d3c7a08ea6313c704ce86fa508be058349 100644 (file)
@@ -41,6 +41,9 @@ NM/04 Fixed exiqgrep to cope with mailq missing size issue
 PP/05 Bugzilla 1083: when lookup expansion defers, escape the output which
       is logged, to avoid truncation. Patch from John Horne.
 
+PP/06 Bugzilla 1042: implement freeze_signal on pipe transports.
+      Patch from Jakob Hirsch.
+
 
 Exim version 4.74
 -----------------
index 55bde992d89ffc19655056c2d1581d8791c03e6d..46fd6c4d865bbfe6e2bead648e3c58457cda7a70 100644 (file)
@@ -18,6 +18,10 @@ Version 4.75
     this: ldap_ca_cert_dir, ldap_ca_cert_file, ldap_cert_file, ldap_cert_key,
     ldap_cipher_suite, ldap_require_cert, ldap_start_tls.
 
+ 2. The pipe transport now takes a boolean option, "freeze_signal", default
+    false.  When true, if the external delivery command exits on a signal then
+    Exim will freeze the message in the queue, instead of generating a bounce.
+
 
 Version 4.74
 ------------
index 2464abd14a6af5b6a75b6829ca6405cf524ef542..a681bc42d46960fd3720839bda54a4db072e7ba8 100644 (file)
@@ -41,6 +41,8 @@ optionlist pipe_transport_options[] = {
       (void *)offsetof(pipe_transport_options_block, escape_string) },
   { "freeze_exec_fail",  opt_bool,
       (void *)offsetof(pipe_transport_options_block, freeze_exec_fail) },
+  { "freeze_signal",     opt_bool,
+      (void *)offsetof(pipe_transport_options_block, freeze_signal) },
   { "ignore_status",     opt_bool,
       (void *)offsetof(pipe_transport_options_block, ignore_status) },
   { "log_defer_output",  opt_bool | opt_public,
@@ -111,6 +113,7 @@ pipe_transport_options_block pipe_transport_option_defaults = {
   60*60,          /* timeout */
   0,              /* options */
   FALSE,          /* freeze_exec_fail */
+  FALSE,          /* freeze_signal */
   FALSE,          /* ignore_status */
   FALSE,          /* permit_coredump */
   FALSE,          /* restrict_to_path */
@@ -960,11 +963,20 @@ if ((rc = child_close(pid, timeout)) != 0)
   /* Either the process completed, but yielded a non-zero (necessarily
   positive) status, or the process was terminated by a signal (rc will contain
   the negation of the signal number). Treat killing by signal as failure unless
-  status is being ignored. */
+  status is being ignored. By default, the message is bounced back, unless
+  freeze_signal is set, in which case it is frozen instead. */
 
   else if (rc < 0)
     {
-    if (!ob->ignore_status)
+    if (ob->freeze_signal)
+      {
+      addr->transport_return = DEFER;
+      addr->special_action = SPECIAL_FREEZE;
+      addr->message = string_sprintf("Child process of %s transport (running "
+        "command \"%s\") was terminated by signal %d (%s)%s", tblock->name, cmd,
+        -rc, os_strsignal(-rc), tmsg);
+      }
+    else if (!ob->ignore_status)
       {
       addr->transport_return = FAIL;
       addr->message = string_sprintf("Child process of %s transport (running "
index da141c0d18a405df70b242adcb09a04e02d31476..765c140928f056a0c85b88333128a1d0ba226a1b 100644 (file)
@@ -24,6 +24,7 @@ typedef struct {
   int   timeout;
   int   options;
   BOOL  freeze_exec_fail;
+  BOOL  freeze_signal;
   BOOL  ignore_status;
   BOOL  permit_coredump;
   BOOL  restrict_to_path;