]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.4-20061210
authorWietse Venema <wietse@porcupine.org>
Sun, 10 Dec 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:43 +0000 (06:32 +0000)
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/src/global/mail_version.h
postfix/src/util/msg.c
postfix/src/util/msg_output.c
postfix/src/util/sys_defs.h
postfix/src/util/vbuf_print.c

index 931279f9a7c53d37811548a950bc841fb92a0baf..952176f91ebca1c608560bacc0ad0ec207f5680e 100644 (file)
@@ -12977,6 +12977,13 @@ Apologies for any names omitted.
        MIME structures in the message body. Victor Duchovni. File:
        smtp/smtp_proto.c.
 
+20061210
+
+       Cleanup: streamline the signal handler reentrancy protections,
+       and document under what conditions these protections work,
+       with REENTRANCY sections in the relevant man pages. Files:
+       util/vbuf.c.  util/msg.c, util/msg_output.c.
+
 Wish list:
 
        Update MILTER_README with Martinec info.
index 98e5f9ad9e0cb7c441d45c5026d8684e293a57a0..68e759d86339f2039fd044821be139b09b2e2e1b 100644 (file)
@@ -20,6 +20,11 @@ before proceeding.
 Incompatible changes with Postfix snapshot 20061209
 ===================================================
 
+The Postfix installation procedure no longer updates main.cf with
+"unknown_local_recipient_reject_code = 450". Four years after the
+introduction of mandatory recipient validation, this transitional
+tool is no longer neeed.
+
 After upgrading Postfix you MUST execute "postfix reload", otherwise
 the queue manager may log a warnings with:
 
@@ -35,24 +40,28 @@ To fix your master.cf file, use "postfix upgrade-configuration"
 followed by "postfix reload".
 
 Small changes were made to the default bounce message templates,
-to prevent HTML-aware software from hiding or removing "<postmaster>"
-and producing really misleading text.
+to prevent HTML-aware software from hiding or removing the text
+"<postmaster>", and producing misleading text.
 
 Major changes with Postfix snapshot 20061209
 ============================================
 
 Better interoperability with non-conforming SMTP servers that reply
-and disconnect before Postfix has sent the end-of-data.
-
-Improved worst-case queue manager performance when deferring or
-bouncing lots of mail. Instead of talking to the bounce or defer
-service directly, this work is now done in the background by the
-error or retry service.  The retry service is new.
-
-Improved worst-case queue manager performance when delivering
-multi-recipient mail. The queue manager now more agressively reloads
-recipients from the queue file as soon as slots become available,
-instead of waiting for slow deliveries to complete.
+and disconnect before Postfix has sent the complete message content.
+
+Improved worst-case (old and new) queue manager performance when
+deferring or bouncing large amounts of mail. Instead of talking to
+the bounce or defer service synchronously, this work is now done
+in the background by the error or retry service.
+
+Improved worst-case (new) queue manager performance when delivering
+multi-recipient mail. The queue manager now proactively reads
+recipients from the queue file, instead of waiting for the slowest
+deliveries to complete before reading in new recipients.  This
+introduces two parameters: default_recipient_refill_limit (how many
+recipient slots to refill at a time) and default_recipient_refill_delay
+(how long to wait between refill operations). These two parameters
+act as defaults for optional per-transport settings.
 
 Incompatible changes with Postfix snapshot 20061006
 ===================================================
index 6461cc4d43cbf7a73695546fcfe7c53c94f57128..ff1b9d834f581a4d17225994d7aab47ffd50c229 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20061209"
+#define MAIL_RELEASE_DATE      "20061210"
 #define MAIL_VERSION_NUMBER    "2.4"
 
 #ifdef SNAPSHOT
index eeb6953f9f878e7a04bbae5a6e9620c9b837f5a3..ae7798017184850c9db6529d9d06ccde22a36c3e 100644 (file)
 /*     name must have been set by calling one of the msg_XXX_init()
 /*     functions (see the SEE ALSO section).
 /*
-/*     The aforementioned logging routines are protected against
-/*     ordinary recursive calls and against re-entry by a signal
-/*     handler.
-/*
-/*     Protection against re-entry by signal handlers requires
-/*     that:
-/* .IP \(bu
-/*     The signal handler must never return. In other words, the
-/*     signal handler must either call _exit(), kill itself with
-/*     a signal, or do both.
-/* .IP \(bu
-/*     The signal handler must not execute before the msg_XXX_init()
-/*     functions complete initialization.
-/* .PP
-/*     When re-entrancy is detected, the requested logging and
-/*     optional cleanup operations are skipped. Skipping the logging
-/*     operation prevents deadlock on Linux releases that use
-/*     mutexes within system library routines such as syslog().
-/*
 /*     msg_error() reports a recoverable error and increments the error
 /*     counter. When the error count exceeds a pre-set limit (default: 13)
 /*     the program terminates by calling msg_fatal().
 /*     current function pointer. Specify a null argument to disable
 /*     this feature.
 /*
-/*     Note: each msg_cleanup() call-back function, and each Postfix
-/*     or system function called by that call-back function, either
-/*     protects itself against recursive calls and re-entry by a
-/*     terminating signal handler, or is called exclusively by
-/*     functions in the msg(3) module.
-/*
 /*     msg_error_limit() sets the error message count limit, and returns.
 /*     the old limit.
 /*
 /*     msg_verbose is a global flag that can be set to make software
 /*     more verbose about what it is doing. By default the flag is zero.
 /*     By convention, a larger value means more noise.
+/* REENTRANCY
+/* .ad
+/* .fi
+/*     The msg_info() etc. output routines are protected against
+/*     ordinary recursive calls and against re-entry by signal
+/*     handlers.
+/*
+/*     Protection against re-entry by signal handlers is subject
+/*     to the following limitations:
+/* .IP \(bu
+/*     The signal handlers must never return. In other words, the
+/*     signal handlers must do one or more of the following: call
+/*     _exit(), kill the process with a signal, and permanently block
+/*     the process.
+/* .IP \(bu
+/*     The signal handlers must invoke msg_info() etc. not until
+/*     after the msg_XXX_init() functions complete initialization,
+/*     and not until after the first formatted output to a VSTRING
+/*     or VSTREAM.
+/* .IP \(bu
+/*     Each msg_cleanup() call-back function, and each Postfix or
+/*     system function invoked by that call-back function, either
+/*     protects itself against recursive calls and re-entry by a
+/*     terminating signal handler, or is called exclusively by the
+/*     msg(3) module.
+/* .PP
+/*     When re-entrancy is detected, the requested output and
+/*     optional cleanup operations are skipped. Skipping the output
+/*     operations prevents memory corruption of VSTREAM_ERR data
+/*     structures, and prevents deadlock on Linux releases that
+/*     use mutexes within system library routines such as syslog().
+/*     This protection exists under the condition that these
+/*     specific resources are accessed exclusively via the msg_info()
+/*     etc.  functions.
 /* SEE ALSO
 /*     msg_output(3) specify diagnostics disposition
 /*     msg_stdio(3) direct diagnostics to standard I/O stream
@@ -150,7 +159,13 @@ static int msg_error_count = 0;
 static int msg_error_bound = 13;
 
  /*
-  * Global scope, to discourage the compiler from doing smart things.
+  * The msg_exiting flag prevents us from recursively reporting an error with
+  * msg_fatal*() or msg_panic(), and provides a first-level safety net for
+  * optional cleanup actions against signal handler re-entry problems. Note
+  * that msg_vprintf() implements its own guard against re-entry.
+  * 
+  * XXX We specify global scope, to discourage the compiler from doing smart
+  * things.
   */
 volatile int msg_exiting = 0;
 
@@ -160,11 +175,9 @@ void    msg_info(const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
     va_start(ap, fmt);
     msg_vprintf(MSG_INFO, fmt, ap);
     va_end(ap);
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
 }
 
 /* msg_warn - report warning message */
@@ -173,11 +186,9 @@ void    msg_warn(const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
     va_start(ap, fmt);
     msg_vprintf(MSG_WARN, fmt, ap);
     va_end(ap);
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
 }
 
 /* msg_error - report recoverable error */
@@ -186,11 +197,9 @@ void    msg_error(const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
     va_start(ap, fmt);
     msg_vprintf(MSG_ERROR, fmt, ap);
     va_end(ap);
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
     if (++msg_error_count >= msg_error_bound)
        msg_fatal("too many errors - program terminated");
 }
@@ -201,13 +210,13 @@ NORETURN msg_fatal(const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
-    va_start(ap, fmt);
-    msg_vprintf(MSG_FATAL, fmt, ap);
-    va_end(ap);
-    if (msg_cleanup_fn)
-       msg_cleanup_fn();
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
+    if (msg_exiting++ == 0) {
+       va_start(ap, fmt);
+       msg_vprintf(MSG_FATAL, fmt, ap);
+       va_end(ap);
+       if (msg_cleanup_fn)
+           msg_cleanup_fn();
+    }
     sleep(1);
     /* In case we're running as a signal handler. */
     _exit(1);
@@ -219,13 +228,13 @@ NORETURN msg_fatal_status(int status, const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
-    va_start(ap, fmt);
-    msg_vprintf(MSG_FATAL, fmt, ap);
-    va_end(ap);
-    if (msg_cleanup_fn)
-       msg_cleanup_fn();
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
+    if (msg_exiting++ == 0) {
+       va_start(ap, fmt);
+       msg_vprintf(MSG_FATAL, fmt, ap);
+       va_end(ap);
+       if (msg_cleanup_fn)
+           msg_cleanup_fn();
+    }
     sleep(1);
     /* In case we're running as a signal handler. */
     _exit(status);
@@ -237,11 +246,11 @@ NORETURN msg_panic(const char *fmt,...)
 {
     va_list ap;
 
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
-    va_start(ap, fmt);
-    msg_vprintf(MSG_PANIC, fmt, ap);
-    va_end(ap);
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
+    if (msg_exiting++ == 0) {
+       va_start(ap, fmt);
+       msg_vprintf(MSG_PANIC, fmt, ap);
+       va_end(ap);
+    }
     sleep(1);
     abort();                                   /* Die! */
     /* In case we're running as a signal handler. */
index b97b9c5ca22bf42276509031ff057a19e6b0078a..ebef3c6cf6756fccd8e5a729ed34817c5355c2e3 100644 (file)
 /*     const char *text;
 /* DESCRIPTION
 /*     This module implements low-level output management for the
-/*     msg(3) diagnostics interface. The output routines are
-/*     protected against ordinary recursive calls and against
-/*     re-entry by a signal handler.
-/*
-/*     Protection against re-entry by a signal handler requires
-/*     that:
-/* .IP \(bu
-/*     The signal handler never returns.
-/* .IP \(bu
-/*     The signal handler does not execute before msg_output()
-/*     completes initialization.
-/* .IP \(bu
-/*     Each msg_output() call-back function, and each Postfix or
-/*     system function called by that call-back function, either
-/*     protects itself against recursive calls and re-entry by a
-/*     terminating signal handler, or is called exclusively by
-/*     functions in the msg_output(3) module.
-/* .PP
-/*     When re-entrancy is detected, the requested output operation
-/*     is skipped. This prevents deadlock on Linux releases that
-/*     use mutexes within system library routines such as syslog().
+/*     msg(3) diagnostics interface.
 /*
 /*     msg_output() registers an output handler for the diagnostics
 /*     interface. An application can register multiple output handlers.
 /*
 /*     msg_text() copies a pre-formatted text, sanitizes the result, and
 /*     calls the output handlers registered with msg_output().
+/* REENTRANCY
+/* .ad
+/* .fi
+/*     The above output routines are protected against ordinary
+/*     recursive calls and against re-entry by signal
+/*     handlers, with the following limitations:
+/* .IP \(bu
+/*     The signal handlers must never return. In other words, the
+/*     signal handlers must do one or more of the following: call
+/*     _exit(), kill the process with a signal, and permanently
+/*     block the process.
+/* .IP \(bu
+/*     The signal handlers must call the above output routines not
+/*     until after msg_output() completes initialization, and not
+/*     until after the first formatted output to a VSTRING or
+/*     VSTREAM.
+/* .IP \(bu
+/*     Each msg_output() call-back function, and each Postfix or
+/*     system function called by that call-back function, either
+/*     must protect itself against recursive calls and re-entry
+/*     by a terminating signal handler, or it must be called
+/*     exclusively by functions in the msg_output(3) module.
+/* .PP
+/*     When re-entrancy is detected, the requested output operation
+/*     is skipped. This prevents memory corruption of VSTREAM_ERR
+/*     data structures, and prevents deadlock on Linux releases
+/*     that use mutexes within system library routines such as
+/*     syslog(). This protection exists under the condition that
+/*     these specific resources are accessed exclusively via
+/*     msg_output() call-back functions.
 /* LICENSE
 /* .ad
 /* .fi
  /*
   * Global scope, to discourage the compiler from doing smart things.
   */
-volatile int msg_vp_lock;
-volatile int msg_txt_lock;
+volatile int msg_vprintf_lock;
+volatile int msg_text_lock;
 
  /*
   * Private state.
@@ -138,10 +148,13 @@ void    msg_printf(int level, const char *format,...)
 
 void    msg_vprintf(int level, const char *format, va_list ap)
 {
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_vp_lock);
-    vstring_vsprintf(msg_buffer, percentm(format, errno), ap);
-    msg_text(level, vstring_str(msg_buffer));
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_vp_lock);
+    if (msg_vprintf_lock == 0) {
+       msg_vprintf_lock = 1;
+       /* OK if terminating signal handler hijacks control before next stmt. */
+       vstring_vsprintf(msg_buffer, percentm(format, errno), ap);
+       msg_text(level, vstring_str(msg_buffer));
+       msg_vprintf_lock = 0;
+    }
 }
 
 /* msg_text - sanitize and log pre-formatted text */
@@ -153,14 +166,17 @@ void    msg_text(int level, const char *text)
     /*
      * Sanitize the text. Use a private copy if necessary.
      */
-    BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_txt_lock);
-    if (text != vstring_str(msg_buffer))
-       vstring_strcpy(msg_buffer, text);
-    printable(vstring_str(msg_buffer), '?');
-    /* On-the-fly initialization for debugging test programs only. */
-    if (msg_output_fn_count == 0)
-       msg_vstream_init("unknown", VSTREAM_ERR);
-    for (i = 0; i < msg_output_fn_count; i++)
-       msg_output_fn[i] (level, vstring_str(msg_buffer));
-    END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_txt_lock);
+    if (msg_text_lock == 0) {
+       msg_text_lock = 1;
+       /* OK if terminating signal handler hijacks control before next stmt. */
+       if (text != vstring_str(msg_buffer))
+           vstring_strcpy(msg_buffer, text);
+       printable(vstring_str(msg_buffer), '?');
+       /* On-the-fly initialization for debugging test programs only. */
+       if (msg_output_fn_count == 0)
+           msg_vstream_init("unknown", VSTREAM_ERR);
+       for (i = 0; i < msg_output_fn_count; i++)
+           msg_output_fn[i] (level, vstring_str(msg_buffer));
+       msg_text_lock = 0;
+    }
 }
index 93cda277db0c93192f674597c5cfe2f5c216eaf4..25c0b40fb37b44c4cec8ed3b64b1d738fd33d7e9 100644 (file)
@@ -1427,28 +1427,6 @@ typedef int pid_t;
   */
 extern int REMOVE(const char *);
 
- /*
-  * Enter, or skip, a critical region. This is used in fatal run-time error
-  * handlers.
-  * 
-  * It is OK if a terminating signal handler hijacks control before the next
-  * statement executes. The interrupted thread will never be resumed; when
-  * the signal handler leaves the critical region, the state of the
-  * "critical" variable can safely be left in an inconsistent state. We
-  * explicitly give the critical variable global scope, to discourage the
-  * compiler from trying to do clever things.
-  */
-#define BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(name) \
-           if (name == 0) { \
-               name = 1;
-
- /*
-  * Leave critical region.
-  */
-#define END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(name) \
-               name = 0; \
-           }
-
 /* LICENSE
 /* .ad
 /* .fi
index e64b15b2e60068a6c57132cdd95d4dd638cbf400..8b9878d33a799552c8ff138e41e69f2c2695abd3 100644 (file)
 /*     In addition, vbuf_print() recognizes the %m format specifier
 /*     and expands it to the error message corresponding to the current
 /*     value of the global \fIerrno\fR variable.
+/* REENTRANCY
+/* .ad
+/* .fi
+/*     vbuf_print() allocates a static buffer. After completion
+/*     of the first vbuf_print() call, this buffer is safe for
+/*     reentrant vbuf_print() calls by (asynchronous) terminating
+/*     signal handlers or by (synchronous) terminating error
+/*     handlers. vbuf_print() initialization typically happens
+/*     upon the first formatted output to a VSTRING or VSTREAM.
+/*
+/*     However, it is up to the caller to ensure that the destination
+/*     VSTREAM or VSTRING buffer is protected against reentrant usage.
 /* LICENSE
 /* .ad
 /* .fi