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:
|
MIME structures in the message body. Victor Duchovni. File:
|
||||||
smtp/smtp_proto.c.
|
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:
|
Wish list:
|
||||||
|
|
||||||
Update MILTER_README with Martinec info.
|
Update MILTER_README with Martinec info.
|
||||||
|
@ -20,6 +20,11 @@ before proceeding.
|
|||||||
Incompatible changes with Postfix snapshot 20061209
|
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
|
After upgrading Postfix you MUST execute "postfix reload", otherwise
|
||||||
the queue manager may log a warnings with:
|
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".
|
followed by "postfix reload".
|
||||||
|
|
||||||
Small changes were made to the default bounce message templates,
|
Small changes were made to the default bounce message templates,
|
||||||
to prevent HTML-aware software from hiding or removing "<postmaster>"
|
to prevent HTML-aware software from hiding or removing the text
|
||||||
and producing really misleading text.
|
"<postmaster>", and producing misleading text.
|
||||||
|
|
||||||
Major changes with Postfix snapshot 20061209
|
Major changes with Postfix snapshot 20061209
|
||||||
============================================
|
============================================
|
||||||
|
|
||||||
Better interoperability with non-conforming SMTP servers that reply
|
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
|
Improved worst-case (old and new) queue manager performance when
|
||||||
bouncing lots of mail. Instead of talking to the bounce or defer
|
deferring or bouncing large amounts of mail. Instead of talking to
|
||||||
service directly, this work is now done in the background by the
|
the bounce or defer service synchronously, this work is now done
|
||||||
error or retry service. The retry service is new.
|
in the background by the error or retry service.
|
||||||
|
|
||||||
Improved worst-case queue manager performance when delivering
|
Improved worst-case (new) queue manager performance when delivering
|
||||||
multi-recipient mail. The queue manager now more agressively reloads
|
multi-recipient mail. The queue manager now proactively reads
|
||||||
recipients from the queue file as soon as slots become available,
|
recipients from the queue file, instead of waiting for the slowest
|
||||||
instead of waiting for slow deliveries to complete.
|
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
|
Incompatible changes with Postfix snapshot 20061006
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20061209"
|
#define MAIL_RELEASE_DATE "20061210"
|
||||||
#define MAIL_VERSION_NUMBER "2.4"
|
#define MAIL_VERSION_NUMBER "2.4"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -45,25 +45,6 @@
|
|||||||
/* name must have been set by calling one of the msg_XXX_init()
|
/* name must have been set by calling one of the msg_XXX_init()
|
||||||
/* functions (see the SEE ALSO section).
|
/* 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
|
/* msg_error() reports a recoverable error and increments the error
|
||||||
/* counter. When the error count exceeds a pre-set limit (default: 13)
|
/* counter. When the error count exceeds a pre-set limit (default: 13)
|
||||||
/* the program terminates by calling msg_fatal().
|
/* the program terminates by calling msg_fatal().
|
||||||
@ -83,12 +64,6 @@
|
|||||||
/* current function pointer. Specify a null argument to disable
|
/* current function pointer. Specify a null argument to disable
|
||||||
/* this feature.
|
/* 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.
|
/* msg_error_limit() sets the error message count limit, and returns.
|
||||||
/* the old limit.
|
/* the old limit.
|
||||||
/*
|
/*
|
||||||
@ -97,6 +72,40 @@
|
|||||||
/* msg_verbose is a global flag that can be set to make software
|
/* 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.
|
/* more verbose about what it is doing. By default the flag is zero.
|
||||||
/* By convention, a larger value means more noise.
|
/* 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
|
/* SEE ALSO
|
||||||
/* msg_output(3) specify diagnostics disposition
|
/* msg_output(3) specify diagnostics disposition
|
||||||
/* msg_stdio(3) direct diagnostics to standard I/O stream
|
/* 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;
|
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;
|
volatile int msg_exiting = 0;
|
||||||
|
|
||||||
@ -160,11 +175,9 @@ void msg_info(const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_INFO, fmt, ap);
|
msg_vprintf(MSG_INFO, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* msg_warn - report warning message */
|
/* msg_warn - report warning message */
|
||||||
@ -173,11 +186,9 @@ void msg_warn(const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_WARN, fmt, ap);
|
msg_vprintf(MSG_WARN, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* msg_error - report recoverable error */
|
/* msg_error - report recoverable error */
|
||||||
@ -186,11 +197,9 @@ void msg_error(const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_ERROR, fmt, ap);
|
msg_vprintf(MSG_ERROR, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
|
||||||
if (++msg_error_count >= msg_error_bound)
|
if (++msg_error_count >= msg_error_bound)
|
||||||
msg_fatal("too many errors - program terminated");
|
msg_fatal("too many errors - program terminated");
|
||||||
}
|
}
|
||||||
@ -201,13 +210,13 @@ NORETURN msg_fatal(const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
if (msg_exiting++ == 0) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_FATAL, fmt, ap);
|
msg_vprintf(MSG_FATAL, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (msg_cleanup_fn)
|
if (msg_cleanup_fn)
|
||||||
msg_cleanup_fn();
|
msg_cleanup_fn();
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
}
|
||||||
sleep(1);
|
sleep(1);
|
||||||
/* In case we're running as a signal handler. */
|
/* In case we're running as a signal handler. */
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@ -219,13 +228,13 @@ NORETURN msg_fatal_status(int status, const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
if (msg_exiting++ == 0) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_FATAL, fmt, ap);
|
msg_vprintf(MSG_FATAL, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (msg_cleanup_fn)
|
if (msg_cleanup_fn)
|
||||||
msg_cleanup_fn();
|
msg_cleanup_fn();
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
}
|
||||||
sleep(1);
|
sleep(1);
|
||||||
/* In case we're running as a signal handler. */
|
/* In case we're running as a signal handler. */
|
||||||
_exit(status);
|
_exit(status);
|
||||||
@ -237,11 +246,11 @@ NORETURN msg_panic(const char *fmt,...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
BEGIN_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
if (msg_exiting++ == 0) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
msg_vprintf(MSG_PANIC, fmt, ap);
|
msg_vprintf(MSG_PANIC, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
END_PROTECT_AGAINST_RECURSION_OR_TERMINATING_SIGNAL_HANDLER(msg_exiting);
|
}
|
||||||
sleep(1);
|
sleep(1);
|
||||||
abort(); /* Die! */
|
abort(); /* Die! */
|
||||||
/* In case we're running as a signal handler. */
|
/* In case we're running as a signal handler. */
|
||||||
|
@ -25,27 +25,7 @@
|
|||||||
/* const char *text;
|
/* const char *text;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module implements low-level output management for the
|
/* This module implements low-level output management for the
|
||||||
/* msg(3) diagnostics interface. The output routines are
|
/* msg(3) diagnostics interface.
|
||||||
/* 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_output() registers an output handler for the diagnostics
|
/* msg_output() registers an output handler for the diagnostics
|
||||||
/* interface. An application can register multiple output handlers.
|
/* interface. An application can register multiple output handlers.
|
||||||
@ -60,6 +40,36 @@
|
|||||||
/*
|
/*
|
||||||
/* msg_text() copies a pre-formatted text, sanitizes the result, and
|
/* msg_text() copies a pre-formatted text, sanitizes the result, and
|
||||||
/* calls the output handlers registered with msg_output().
|
/* 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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -90,8 +100,8 @@
|
|||||||
/*
|
/*
|
||||||
* Global scope, to discourage the compiler from doing smart things.
|
* Global scope, to discourage the compiler from doing smart things.
|
||||||
*/
|
*/
|
||||||
volatile int msg_vp_lock;
|
volatile int msg_vprintf_lock;
|
||||||
volatile int msg_txt_lock;
|
volatile int msg_text_lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private state.
|
* 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)
|
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);
|
vstring_vsprintf(msg_buffer, percentm(format, errno), ap);
|
||||||
msg_text(level, vstring_str(msg_buffer));
|
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 */
|
/* 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.
|
* 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))
|
if (text != vstring_str(msg_buffer))
|
||||||
vstring_strcpy(msg_buffer, text);
|
vstring_strcpy(msg_buffer, text);
|
||||||
printable(vstring_str(msg_buffer), '?');
|
printable(vstring_str(msg_buffer), '?');
|
||||||
@ -162,5 +177,6 @@ void msg_text(int level, const char *text)
|
|||||||
msg_vstream_init("unknown", VSTREAM_ERR);
|
msg_vstream_init("unknown", VSTREAM_ERR);
|
||||||
for (i = 0; i < msg_output_fn_count; i++)
|
for (i = 0; i < msg_output_fn_count; i++)
|
||||||
msg_output_fn[i] (level, vstring_str(msg_buffer));
|
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 *);
|
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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@ -20,6 +20,18 @@
|
|||||||
/* In addition, vbuf_print() recognizes the %m format specifier
|
/* In addition, vbuf_print() recognizes the %m format specifier
|
||||||
/* and expands it to the error message corresponding to the current
|
/* and expands it to the error message corresponding to the current
|
||||||
/* value of the global \fIerrno\fR variable.
|
/* 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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user