20030609
+ Workaround: Solaris blocking socket read() may hang. Hernan
+ Perez Masci and Leandro Santi. File: smtpd/smtpd.c.
+
Bugfix: the "unread recipient" counter needs to be restored
after the queue manager has a problem reading a queue file.
- This fix is for purists only, because after such a failure
- Postfix closes the queue file and parks it in the corrupt
- queue. Fix by Patrik Rak. File: nqmgr/qmgr_message.c.
+ Fix by Patrik Rak. File: nqmgr/qmgr_message.c.
+
+20030610
+
+ Cleanup: the verify server now uses asynchronous submission
+ of mail probes, so it will no longer block for in_flow_delay
+ seconds when mail arrives faster than it is delivered.
+ Still need to make mail_stream_finish() asynchronous in
+ order to avoid blocking for trigger_timeout seconds when the
+ queue manager is overwhelmed. Files: global/post_mail.c,
+ verify/verify.c.
+
+ Bugfix: removed extraneous sleep() after the last attempt
+ to retrieve address verification status. File: smtpd/smtpd.c.
+
+20030611
+
+ Bugfix: the stricter postdrop input filter broke "sendmail
+ -bs". Found by Lutz Jaenicke. File: smtpd/smtpd.c.
Open problems:
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
+Major changes with Postfix snapshot 2.0.11-20030611
+===================================================
+
+Better verify server performance on busy servers by avoiding some
+operations that can block the verify server process temporarily.
+Probe messages are no longer subject to cleanup server in_flow_delay
+settings when message arrival rates exceed message delivery rates.
+However, probe messages are still subject to trigger_timeout delays
+when the queue manager FIFO fills up; this is hopefully very rare.
+
Major changes with Postfix snapshot 2.0.11-20030609
===================================================
Problems and transactions are logged to <b>syslogd</b>(8).
<b>BUGS</b>
- This prototype server uses synchronous submission for
- sending a probe message, which can be slow on a busy
- machine.
-
If the persistent database ever gets corrupted then the
world comes to an end and human intervention is needed.
This violates a basic Postfix principle.
.SH BUGS
.ad
.fi
-This prototype server uses synchronous submission for sending
-a probe message, which can be slow on a busy machine.
-
If the persistent database ever gets corrupted then the world
comes to an end and human intervention is needed. This violates
a basic Postfix principle.
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030609"
+#define MAIL_RELEASE_DATE "20030611"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.11-" MAIL_RELEASE_DATE
+#define DEF_MAIL_VERSION "2.0.12-" MAIL_RELEASE_DATE
extern char *var_mail_version;
/*
/* int cleanup_flags;
/* int trace_flags;
/*
-/* VSTREAM *post_mail_fopen_nowait(sender, recipient,
+/* VSTREAM *post_mail_fopen_nowait(sender, recipient,
/* cleanup_flags, trace_flags)
/* const char *sender;
/* const char *recipient;
/* int cleanup_flags;
/* int trace_flags;
/*
-/* VSTREAM *post_mail_fopen_async(sender, recipient,
+/* void post_mail_fopen_async(sender, recipient,
/* cleanup_flags, trace_flags,
/* notify, context)
/* const char *sender;
/* const char *recipient;
/* int cleanup_flags;
/* int trace_flags;
-/* void (*notify)(char *context);
+/* void (*notify)(VSTREAM *stream, char *context);
/* char *context;
/*
/* int post_mail_fprintf(stream, format, ...)
/*
/* post_mail_fopen_async() contacts the cleanup service and
/* invokes the caller-specified notify routine, with the
-/* caller-specified context, when the service responds.
-/* IMPORTANT NOTE: closing the stream will not cancel any
-/* pending I/O or timeout call-back notification.
+/* open stream and the caller-specified context when the
+/* service responds, or with a null stream and the caller-specified
+/* context when the request could not be completed. It is the
+/* responsability of the application to close an open stream.
/*
/* post_mail_fprintf() formats message content (header or body)
/* and sends it to the cleanup service.
post_mail_init(state->stream, state->sender,
state->recipient, state->cleanup_flags,
state->trace_flags);
- state->notify(state->context);
myfree(state->sender);
myfree(state->recipient);
+ state->notify(state->stream, state->context);
myfree((char *) state);
return;
* limit. The system is broken and we give up.
*/
case EVENT_TIME:
- msg_fatal("timeout connecting to service: %s", var_cleanup_service);
+ if (state->stream) {
+ msg_warn("timeout connecting to service: %s", var_cleanup_service);
+ event_disable_readwrite(vstream_fileno(state->stream));
+ vstream_fclose(state->stream);
+ } else {
+ msg_warn("connect to service: %s: %m", var_cleanup_service);
+ }
+ myfree(state->sender);
+ myfree(state->recipient);
+ state->notify((VSTREAM *) 0, state->context);
+ myfree((char *) state);
+ return;
/*
* Broken software or hardware.
/* post_mail_fopen_async - prepare for posting a message */
-VSTREAM *post_mail_fopen_async(const char *sender, const char *recipient,
- int cleanup_flags, int trace_flags,
- void (*notify) (void *), void *context)
+void post_mail_fopen_async(const char *sender, const char *recipient,
+ int cleanup_flags, int trace_flags,
+ void (*notify) (VSTREAM *, void *),
+ void *context)
{
VSTREAM *stream;
POST_MAIL_STATE *state;
stream = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service, NON_BLOCKING);
+ state = (POST_MAIL_STATE *) mymalloc(sizeof(*state));
+ state->sender = mystrdup(sender);
+ state->recipient = mystrdup(recipient);
+ state->cleanup_flags = cleanup_flags;
+ state->trace_flags = trace_flags;
+ state->notify = notify;
+ state->context = context;
+ state->stream = stream;
+
+ /*
+ * To keep interfaces as simple as possible we report all errors via the
+ * same interface as all successes.
+ */
if (stream != 0) {
- state = (POST_MAIL_STATE *) mymalloc(sizeof(*state));
- state->sender = mystrdup(sender);
- state->recipient = mystrdup(recipient);
- state->cleanup_flags = cleanup_flags;
- state->trace_flags = trace_flags;
- state->notify = notify;
- state->context = context;
- state->stream = stream;
event_enable_write(vstream_fileno(stream), post_mail_open_event,
(void *) state);
event_request_timer(post_mail_open_event, (void *) state,
var_daemon_timeout);
+ } else {
+ event_request_timer(post_mail_open_event, (void *) state, 0);
}
- return (stream);
}
/* post_mail_fprintf - format and send message content */
/*
* External interface.
*/
-typedef void (*POST_MAIL_NOTIFY)(void *);
+typedef void (*POST_MAIL_NOTIFY)(VSTREAM *, void *);
extern VSTREAM *post_mail_fopen(const char *, const char *, int, int);
extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int);
-extern VSTREAM *post_mail_fopen_async(const char *, const char *, int, int, POST_MAIL_NOTIFY, void *);
+extern void post_mail_fopen_async(const char *, const char *, int, int, POST_MAIL_NOTIFY, void *);
extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
extern int post_mail_fputs(VSTREAM *, const char *);
extern int post_mail_buffer(VSTREAM *, const char *, int);
/*
* Record the time of arrival and the sender envelope address.
*/
- rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
- (long) time((time_t *) 0));
- if (*var_filter_xport)
- rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
+ if (SMTPD_STAND_ALONE(state) == 0) {
+ rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
+ (long) time((time_t *) 0));
+ if (*var_filter_xport)
+ rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
+ }
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
if (encoding != 0)
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
/*
* Verify the address. Don't waste too much of their or our time.
*/
- for (count = 0; count < 3; count++) {
+ for (count = 0; /* see below */ ; count++) {
verify_status = verify_clnt_query(addr, &rcpt_status, why);
if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO)
break;
+ if (count >= 2)
+ break;
sleep(3);
}
if (verify_status != VRFY_STAT_OK) {
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
-/* This prototype server uses synchronous submission for sending
-/* a probe message, which can be slow on a busy machine.
-/*
/* If the persistent database ever gets corrupted then the world
/* comes to an end and human intervention is needed. This violates
/* a basic Postfix principle.
vstring_free(text);
}
+/* verify_post_mail_action - callback */
+
+static void verify_post_mail_action(VSTREAM *stream, void *unused_context)
+{
+
+ /*
+ * Probe messages need no body content, because they are never delivered,
+ * deferred, or bounced.
+ */
+ if (stream != 0)
+ post_mail_fclose(stream);
+}
+
/* verify_query_service - query address status */
static void verify_query_service(VSTREAM *client_stream)
if (msg_verbose)
msg_info("PROBE %s status=%d probed=%ld updated=%ld",
STR(addr), addr_status, now, updated);
- if ((post = post_mail_fopen(strcmp(var_verify_sender, "<>") == 0 ?
- "" : var_verify_sender, STR(addr),
- NULL_CLEANUP_FLAGS,
- DEL_REQ_FLAG_VERIFY)) != 0
- && post_mail_fclose(post) == 0
- && (updated != 0 || var_verify_neg_cache != 0)) {
+ post_mail_fopen_async(strcmp(var_verify_sender, "<>") == 0 ?
+ "" : var_verify_sender, STR(addr),
+ NULL_CLEANUP_FLAGS,
+ DEL_REQ_FLAG_VERIFY,
+ verify_post_mail_action,
+ (void *) 0);
+ if (updated != 0 || var_verify_neg_cache != 0) {
put_buf = vstring_alloc(10);
verify_make_entry(put_buf, addr_status, now, updated, text);
if (msg_verbose)