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:
parent
32c25f2151
commit
39feae3a7e
@ -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.
|
||||
|
@ -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
|
||||
===================================================
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user