Wietse Venema wrote:
Reid Sutherland:
Hi,

Why does Postfix bounce on command execution failure,

The action depends on the command exit status. If you want Postfix
to retry, return the appropriate status.


Not fair, here was our problem:

Final-Recipient: rfc822; r...@vianet.ca
Original-Recipient: rfc822;sxxxx...@vianet.ca
Action: failed
Status: 5.3.0
Diagnostic-Code: x-unix; Can't load '/usr/lib/perl5/auto/Unix/Syslog/Syslog.so' for module Unix::Syslog: /usr/lib/perl5/auto/Unix/Syslog/Syslog.so: failed
    to map segment from shared object: Cannot allocate memory at
/usr/lib/perl/5.14/DynaLoader.pm line 184. at /usr/local/bin/mailhandler line 6 Compilation failed in require at /usr/local/bin/mailhandler line 6.
    BEGIN failed--compilation aborted at /usr/local/bin/mailhandler line 6.


This is the result of an out-of-memory condition caused by a failing disk array. The spawn count was set to high so the OOM condition was triggered. While this was a mistake on our part, out of admin control execution failures should defer.

We also had to use the following hack to ensure module load failures do not result in bounces. I see that Unix::Syslog is absent from the this list or the above bounce may have been prevented.


eval {
  require DBI;
  require Email::Simple::FromHandle;
  require CDB_File;
  require IPC::Open3;
};
my ($exit, $fail_temp, $fail_temp_ex, $fail_perm, $fail_quota_ex, $fail_loop_ex) = (0, 75, '4.3.0', 69, '5.2.2', '5.4.6');
if (!$@) {
  import DBI;
  import Email::Simple::FromHandle;
  import CDB_File;
  import IPC::Open3;
} else {
  warn "mailhandler: module load failed: $@";
  exit ($fail_temp);
}




or on command timeout?

I don't think that it is a good idea to fill up your machine with
programs that keep timing out again and again and again. Postfix
is not only about performance and security, but also about safety
(mail servers should be able to deal with problems and not require
a human babysitter).



Understood, but if this condition is occurring, there must be delay or failure in another component of the system. This is assuming the system is in production and normally functioning. It's too harsh to assume the timing out program is forever guilty of blocking the message. Deferral seems reasonable because the admin must locate and correct the source of the delay.



  This isn't a situation for a hard failure, please clarify the
reasoning.

  From postfix-2.11.7/src/global/pipe_command.c:672

          } else if (write_status && write_errno != EPIPE) {
              vstring_prepend(why->reason, "Command failed: ",
                              sizeof("Command failed: ") - 1);
              vstring_sprintf_append(why->reason, ": \"%s\"", args.command);
              return (PIPE_STAT_BOUNCE);

That is a write error, and the logfile tells you what the problem
is.  The write(2) may fail for a bazillion reasons, some bad and
some not so bad. Returning the mail is the safe action to take.



Sorry, this wasn't the correct snippet, but this was also of concern. I think a local filesystem error would result in a deferral, I can't see why a command would be any different.

Here is the correct snippet from postfix-2.11.7/src/global/pipe_command.c:657:

            /*
             * No "D.S.N text" or <sysexits.h> compatible status. Fake it.
             */
            else {
                sp = sys_exits_detail(WEXITSTATUS(wait_status));
                dsb_unix(why, sp->dsn,
                         log_len ? log_buf : sp->text,
                         "Command died with status %d: \"%s\"%s%s",
                         WEXITSTATUS(wait_status), args.command,
                         log_len ? ". Command output: " : "", log_buf);
                return (PIPE_STAT_BOUNCE);
            }



I think a bounce should only occur if the command explicitly returns it. If the command cannot respond properly for whatever reason, it should be assumed something is wrong and defer.

Thank you for your time.

Reply via email to