events.c handler, undid some unnecessary changes to the
{read,write}{_wait,able}.c modules, and addressed Victor's
paranoia for multi-client servers with a thousand clients
- while linked with third-party libraries that can't handle
- file descriptors >= FD_SETSIZE.
+ while linked with library routines that can't handle file
+ descriptors >= FD_SETSIZE.
+
+ Cleanup: while debugging the new events.c handler, removed
+ an unnecessary "write after connect" call-back event. File:
+ global/post_mail.c.
+
+20070214
+
+ Robustness: in the queue manager keep a number of free file
+ descriptor slots at the low end, to work around library
+ routines that can't handle file descriptors >= FD_SETSIZE.
+ Files: *qmgr/qmgr_transport.c, util/vstream.[hc]
Wish list:
+++ /dev/null
-P\bPo\bos\bst\btf\bfi\bix\bx L\bLM\bMT\bTP\bP H\bHo\bow\bwt\bto\bo
-
--------------------------------------------------------------------------------
-This document will be made available via http://www.postfix.org/.
-
delivery to mailbox servers such as Cyrus. The advantage of this setup is
that one Postfix machine can feed multiple mailbox servers over LMTP. The
opposite is true as well: one mailbox server can be fed over LMTP by
- multiple Postfix machines. The LMTP_README document gives examples of how
- to use the lmtp(8) client.
+ multiple Postfix machines.
* The local(8) delivery agent understands UNIX-style mailboxes, qmail-
compatible maildir files, Sendmail-style system-wide aliases(5) databases,
$readme_directory/IPV6_README:f:root:-:644
$readme_directory/LDAP_README:f:root:-:644
$readme_directory/LINUX_README:f:root:-:644
-$readme_directory/LMTP_README:f:root:-:644
$readme_directory/LOCAL_RECIPIENT_README:f:root:-:644
$readme_directory/MACOSX_README:f:root:-:644:o
$readme_directory/MAILDROP_README:f:root:-:644
$html_directory/IPV6_README.html:f:root:-:644
$html_directory/LDAP_README.html:f:root:-:644
$html_directory/LINUX_README.html:f:root:-:644
-$html_directory/LMTP_README.html:f:root:-:644
$html_directory/LOCAL_RECIPIENT_README.html:f:root:-:644
$html_directory/MAILDROP_README.html:f:root:-:644
$html_directory/MILTER_README.html:f:root:-:644
+++ /dev/null
-<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-
-<head>
-
-<title>Postfix LMTP Howto</title>
-
-<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
-
-</head>
-
-<body>
-
-<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix LMTP Howto</h1>
-
-<hr>
-
-<p> This document will be made available via <a href="http://www.postfix.org/">http://www.postfix.org/</a>. </p>
-
-</body>
-
-</html>
advantage of this setup is that one Postfix machine can feed multiple
mailbox servers over LMTP. The opposite is true as well: one
mailbox server can be fed over LMTP by multiple Postfix machines.
-The <a href="LMTP_README.html">LMTP_README</a> document gives examples of how to use the <a href="lmtp.8.html">lmtp(8)</a>
-client. </p>
+</p>
<li> <p> The <a href="local.8.html">local(8)</a> delivery agent understands UNIX-style mailboxes,
qmail-compatible maildir files, Sendmail-style system-wide <a href="aliases.5.html">aliases(5)</a>
# Do not build with Linux EPOLL support.
# By default, EPOLL support is compiled in on platforms that
# are known to support it.
+# .IP \fB-DNO_KQUEUE\fR
+# Do not build with FreeBSD/NetBSD/OpenBSD KQUEUE support.
+# By default, KQUEUE support is compiled in on platforms that
+# are known to support it.
# .IP \fB-DNO_IPV6\fR
# Do not build with IPv6 support.
# By default, IPv6 support is compiled in on platforms that
SunOS.5*) SYSTYPE=SUNOS5
RANLIB=echo
SYSLIBS="-lresolv -lsocket -lnsl"
- # Solaris 8 added usleep() and POSIX regular expressions
+ # Solaris 5 added usleep() and POSIX regular expressions
case $RELEASE in
5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP";;
esac
+++ /dev/null
-<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-
-<head>
-
-<title>Postfix LMTP Howto</title>
-
-<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
-
-</head>
-
-<body>
-
-<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix LMTP Howto</h1>
-
-<hr>
-
-<p> This document will be made available via http://www.postfix.org/. </p>
-
-</body>
-
-</html>
../html/ETRN_README.html ../html/FILTER_README.html \
../html/INSTALL.html ../html/IPV6_README.html \
../html/LDAP_README.html \
- ../html/LINUX_README.html ../html/LMTP_README.html \
+ ../html/LINUX_README.html \
../html/LOCAL_RECIPIENT_README.html ../html/MAILDROP_README.html \
../html/MILTER_README.html \
../html/MYSQL_README.html ../html/NFS_README.html \
../README_FILES/ETRN_README ../README_FILES/FILTER_README \
../README_FILES/INSTALL ../README_FILES/IPV6_README \
../README_FILES/LDAP_README \
- ../README_FILES/LINUX_README ../README_FILES/LMTP_README \
+ ../README_FILES/LINUX_README \
../README_FILES/LOCAL_RECIPIENT_README ../README_FILES/MAILDROP_README \
../README_FILES/MILTER_README \
../README_FILES/MYSQL_README ../README_FILES/NFS_README \
../html/LINUX_README.html: LINUX_README.html
$(POSTLINK) $? >$@
-../html/LMTP_README.html: LMTP_README.html
- $(POSTLINK) $? >$@
-
../html/LOCAL_RECIPIENT_README.html: LOCAL_RECIPIENT_README.html
$(POSTLINK) $? >$@
../README_FILES/LINUX_README: LINUX_README.html
$(HT2READ) $? >$@
-../README_FILES/LMTP_README: LMTP_README.html
- $(HT2READ) $? >$@
-
../README_FILES/LOCAL_RECIPIENT_README: LOCAL_RECIPIENT_README.html
$(HT2READ) $? >$@
advantage of this setup is that one Postfix machine can feed multiple
mailbox servers over LMTP. The opposite is true as well: one
mailbox server can be fed over LMTP by multiple Postfix machines.
-The LMTP_README document gives examples of how to use the lmtp(8)
-client. </p>
+</p>
<li> <p> The local(8) delivery agent understands UNIX-style mailboxes,
qmail-compatible maildir files, Sendmail-style system-wide aliases(5)
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20070212"
+#define MAIL_RELEASE_DATE "20070214"
#define MAIL_VERSION_NUMBER "2.4"
#ifdef SNAPSHOT
#include <sys_defs.h>
#include <unistd.h>
+#include <sys/time.h> /* FD_SETSIZE */
+#include <sys/types.h> /* FD_SETSIZE */
+#include <unistd.h> /* FD_SETSIZE */
+
+#ifdef USE_SYS_SELECT_H
+#include <sys/select.h> /* FD_SETSIZE */
+#endif
+
/* Utility library. */
#include <msg.h>
event_request_timer(qmgr_transport_event, (char *) alloc, 0);
return;
}
+#if !defined(USE_SELECT_EVENTS) && defined(VSTREAM_CTL_DUPFD)
+ vstream_control(alloc->stream,
+ VSTREAM_CTL_DUPFD, FD_SETSIZE / 8,
+ VSTREAM_CTL_END);
+#endif
event_enable_read(vstream_fileno(alloc->stream), qmgr_transport_event,
(char *) alloc);
#include <sys_defs.h>
#include <unistd.h>
+#include <sys/time.h> /* FD_SETSIZE */
+#include <sys/types.h> /* FD_SETSIZE */
+#include <unistd.h> /* FD_SETSIZE */
+
+#ifdef USE_SYS_SELECT_H
+#include <sys/select.h> /* FD_SETSIZE */
+#endif
+
/* Utility library. */
#include <msg.h>
event_request_timer(qmgr_transport_event, (char *) alloc, 0);
return;
}
+#if !defined(USE_SELECT_EVENTS) && defined(VSTREAM_CTL_DUPFD)
+ vstream_control(alloc->stream,
+ VSTREAM_CTL_DUPFD, FD_SETSIZE / 8,
+ VSTREAM_CTL_END);
+#endif
event_enable_read(vstream_fileno(alloc->stream), qmgr_transport_event,
(char *) alloc);
(event_count) = kevent(event_kq, (struct kevent *) 0, 0, (event_buf), \
(buflen), (tsp)); \
} while (0)
+#define EVENT_BUFFER_READ_TEXT "kevent"
/*
* Macros to process event buffers from the kernel; see event_loop().
dvpoll.dp_timeout = (delay) < 0 ? -1 : (delay) * 1000; \
(event_count) = ioctl(event_pollfd, DP_POLL, &dvpoll); \
} while (0)
+#define EVENT_BUFFER_READ_TEXT "ioctl DP_POLL"
/*
* Macros to process event buffers from the kernel; see event_loop().
(event_count) = epoll_wait(event_epollfd, (event_buf), (buflen), \
(delay) < 0 ? -1 : (delay) * 1000); \
} while (0)
+#define EVENT_BUFFER_READ_TEXT "epoll_wait"
/*
* Macros to process event buffers from the kernel; see event_loop().
#else
EVENT_BUFFER event_buf[100];
EVENT_BUFFER *bp;
- int event_count;
#endif
+ int event_count;
EVENT_TIMER *timer;
int fd;
EVENT_FDTABLE *fdp;
wmask = event_wmask;
xmask = event_xmask;
- if (select(event_max_fd + 1, &rmask, &wmask, &xmask, tvp) < 0) {
+ event_count = select(event_max_fd + 1, &rmask, &wmask, &xmask, tvp);
+ if (event_count < 0) {
if (errno != EINTR)
msg_fatal("event_loop: select: %m");
return;
select_delay);
if (event_count < 0) {
if (errno != EINTR)
- msg_fatal("event_loop: kevent: %m");
+ msg_fatal("event_loop: " EVENT_BUFFER_READ_TEXT ": %m");
return;
}
#endif
* application to determine when a read or write is complete.
*/
#ifdef USE_SELECT_EVENTS
- for (fd = 0; fd <= event_max_fd; fd++) {
+ for (fd = 0; event_count > 0 && fd <= event_max_fd; fd++) {
if (FD_ISSET(fd, &event_xmask)) {
/* In case event_fdtable is updated. */
fdp = event_fdtable + fd;
# define USE_SYSV_POLL
#endif
-#if (defined(__FreeBSD_version) && __FreeBSD_version >= 410000) \
+#ifndef NO_KQUEUE
+# if (defined(__FreeBSD_version) && __FreeBSD_version >= 410000) \
|| (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 200000000) \
|| (defined(OpenBSD) && OpenBSD >= 200105) /* OpenBSD 2.9 */
-# define USE_KQUEUE_EVENTS
+# define USE_KQUEUE_EVENTS
+# endif
#endif
#endif
/* The argument specifies the file descriptor to be used for writing.
/* This feature is limited to double-buffered streams, and makes the
/* stream non-seekable.
+/* .IP "VSTREAM_CTL_DUPFD (int)"
+/* The argument specifies a minimum file descriptor value. If
+/* the actual stream's file descriptors are below the minimum,
+/* reallocate the descriptors to the first free value greater
+/* than or equal to the minimum. The VSTREAM_CTL_DUPFD macro
+/* is defined only on systems with fcntl() F_DUPFD support.
/* .IP "VSTREAM_CTL_WAITPID_FN (int (*)(pid_t, WAIT_STATUS_T *, int))"
/* A pointer to function that behaves like waitpid(). This information
/* is used by the vstream_pclose() routine.
{
const char *myname = "vstream_control";
va_list ap;
+ int floor;
+ int old_fd;
for (va_start(ap, name); name != VSTREAM_CTL_END; name = va_arg(ap, int)) {
switch (name) {
if (stream->jbuf == 0)
stream->jbuf = (jmp_buf *) mymalloc(sizeof(jmp_buf));
break;
+
+#ifdef VSTREAM_CTL_DUPFD
+
+#define VSTREAM_TRY_DUPFD(backup, fd, floor) do { \
+ if (((backup) = (fd)) < floor) { \
+ if (((fd) = fcntl((backup), F_DUPFD, (floor))) < 0) \
+ msg_fatal("fcntl F_DUPFD %d: %m", (floor)); \
+ (void) close(backup); \
+ } \
+ } while (0)
+
+ case VSTREAM_CTL_DUPFD:
+ floor = va_arg(ap, int);
+ if (stream->buf.flags & VSTREAM_FLAG_DOUBLE) {
+ VSTREAM_TRY_DUPFD(old_fd, stream->read_fd, floor);
+ if (stream->write_fd == old_fd)
+ stream->write_fd = stream->read_fd;
+ else
+ VSTREAM_TRY_DUPFD(old_fd, stream->write_fd, floor);
+ } else {
+ VSTREAM_TRY_DUPFD(old_fd, stream->fd, floor);
+ }
+ break;
+#endif
default:
msg_panic("%s: bad name %d", myname, name);
}
#define VSTREAM_CTL_TIMEOUT 8
#define VSTREAM_CTL_EXCEPT 9
#define VSTREAM_CTL_CONTEXT 10
+#ifdef F_DUPFD
+#define VSTREAM_CTL_DUPFD 11
+#endif
extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);