2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

postfix-2.4-20061210

This commit is contained in:
Wietse Venema 2006-12-10 00:00:00 -05:00 committed by Viktor Dukhovni
parent 32c25f2151
commit 39feae3a7e
7 changed files with 153 additions and 122 deletions

View 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.

View 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.
and disconnect before Postfix has sent the complete message content.
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 (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 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.
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
===================================================

View 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

View File

@ -45,25 +45,6 @@
/* 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().
@ -83,12 +64,6 @@
/* 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.
/*
@ -97,6 +72,40 @@
/* 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);
if (msg_exiting++ == 0) {
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);
}
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);
if (msg_exiting++ == 0) {
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);
}
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);
if (msg_exiting++ == 0) {
va_start(ap, fmt);
msg_vprintf(MSG_PANIC, fmt, ap);
va_end(ap);
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
}
sleep(1);
abort(); /* Die! */
/* In case we're running as a signal handler. */

View File

@ -25,27 +25,7 @@
/* 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.
@ -60,6 +40,36 @@
/*
/* 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
@ -90,8 +100,8 @@
/*
* 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);
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));
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_vp_lock);
msg_vprintf_lock = 0;
}
}
/* msg_text - sanitize and log pre-formatted text */
@ -153,7 +166,9 @@ 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 (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), '?');
@ -162,5 +177,6 @@ void msg_text(int level, const char *text)
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);
msg_text_lock = 0;
}
}

View 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

View File

@ -20,6 +20,18 @@
/* 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