From 57cf9e9793856fc9244daf74ca03fa920e801b2c Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 20 Jul 2001 00:00:00 -0500 Subject: [PATCH] snapshot-20010720 --- postfix/HISTORY | 13 ++++ postfix/conf/main.cf | 3 +- postfix/conf/sample-smtpd.cf | 3 +- postfix/src/cleanup/Makefile.in | 1 + postfix/src/cleanup/cleanup.c | 1 + postfix/src/global/mail_params.c | 3 + postfix/src/global/mail_params.h | 11 +++ postfix/src/global/mail_version.h | 2 +- postfix/src/master/Makefile.in | 20 ++++- postfix/src/master/mail_flow.c | 112 ++++++++++++++++++++++++++++ postfix/src/master/mail_flow.h | 31 ++++++++ postfix/src/master/mail_server.h | 2 + postfix/src/master/master.c | 6 +- postfix/src/master/master.h | 6 ++ postfix/src/master/master_flow.c | 30 ++++++++ postfix/src/master/master_proto.h | 12 ++- postfix/src/master/master_spawn.c | 17 +++++ postfix/src/master/multi_server.c | 2 + postfix/src/master/single_server.c | 10 +++ postfix/src/master/trigger_server.c | 2 + postfix/src/nqmgr/qmgr.c | 12 +++ postfix/src/postalias/postalias.c | 3 - postfix/src/postmap/postmap.c | 3 - postfix/src/qmgr/qmgr.c | 12 +++ 24 files changed, 301 insertions(+), 16 deletions(-) create mode 100644 postfix/src/master/mail_flow.c create mode 100644 postfix/src/master/mail_flow.h create mode 100644 postfix/src/master/master_flow.c diff --git a/postfix/HISTORY b/postfix/HISTORY index 5fce918f4..a000faf3e 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5347,3 +5347,16 @@ Apologies for any names omitted. Logging: the queue manager now logs a "status=expired" record when it returns a message that is too old. Files: *qmgr/qmgr_active.c. + +20010719 + + Feature: stiffer coupling between mail arrival rates and + mail delivery rates, using a trivial token-based scheme + where qmgr provides a token when it retrieves mail from + the incoming queue, and where the cleanup daemon wants a + token after enqueueing mail. If no token is available the + cleanup server pauses briefly and proceeds anyway. This + allows input rates to gradually exceed output rates. After + sustained exposure to high input loads Postfix reverts to + the old situation where it sacrifices output rates in favor + of receiving mail. diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 1612b1d45..8807373a4 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -163,7 +163,8 @@ mail_owner = postfix # address. # # You can also specify the absolute pathname of a pattern file instead -# of listing the patterns here. +# of listing the patterns here. Specify type:name for table-based lookups +# (the value on the table right-hand side is not used). # #mynetworks = 168.100.189.0/28, 127.0.0.0/8 #mynetworks = $config_directory/mynetworks diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index c0ff345f4..1429a5e74 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -135,7 +135,8 @@ mynetworks_style = subnet # address. # # You can also specify the absolute pathname of a pattern file instead -# of listing the patterns here. +# of listing the patterns here. Specify type:name for table-based lookups +# (the value on the table right-hand side is not used). # #mynetworks = 168.100.189.0/28, 127.0.0.0/8 #mynetworks = $config_directory/mynetworks diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 168040d94..75d74b513 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -75,6 +75,7 @@ cleanup.o: ../../include/iostuff.h cleanup.o: ../../include/mail_params.h cleanup.o: ../../include/record.h cleanup.o: ../../include/rec_type.h +cleanup.o: ../../include/mail_flow.h cleanup.o: ../../include/mail_server.h cleanup.o: cleanup.h cleanup.o: ../../include/maps.h diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 70476aa2e..9891a03cc 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -271,5 +271,6 @@ int main(int argc, char **argv) MAIL_SERVER_PRE_INIT, cleanup_pre_jail, MAIL_SERVER_POST_INIT, cleanup_post_jail, MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_FLOW_CTL, 0); } diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 6fc2db082..ec3d78064 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -69,6 +69,7 @@ /* char *var_export_environ; /* char *var_debug_peer_list; /* int var_debug_peer_level; +/* int var_glob_flow_ctl; /* /* void mail_params_init() /* DESCRIPTION @@ -185,6 +186,7 @@ char *var_def_transport; char *var_mynetworks_style; char *var_verp_delims; char *var_verp_filter; +int var_glob_flow_ctl; char *var_import_environ; char *var_export_environ; @@ -325,6 +327,7 @@ void mail_params_init() VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0, VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0, VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0, + VAR_GLOB_FLOW_CTL, DEF_GLOB_FLOW_CTL, &var_glob_flow_ctl, 0, 0, 0, }; static CONFIG_TIME_TABLE time_defaults[] = { diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 30b163489..7c6744d2d 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1283,6 +1283,17 @@ extern char *var_verp_delims; #define DEF_VERP_FILTER "-=+" extern char *var_verp_filter; + /* + * Global flow control. This allows for a stiffer coupling between receiving + * programs and the queue manager, so that receiving processes cannot easily + * overwhelm the file system. The coupling is not so tight that Postfix + * stops receiving mail althogether. It just slows down a bit so that + * sending processes get a chance to read from the disk. + */ +#define VAR_GLOB_FLOW_CTL "global_mail_flow_control" +#define DEF_GLOB_FLOW_CTL 0 +extern int var_glob_flow_ctl; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index e53ebfb00..b2a510397 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20010714" +#define DEF_MAIL_VERSION "Snapshot-20010720" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index d33912054..59f1e3cc8 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -2,12 +2,13 @@ SHELL = /bin/sh SRCS = master.c master_conf.c master_ent.c master_sig.c master_avail.c \ master_spawn.c master_service.c master_status.o master_listen.c \ master_proto.c single_server.c multi_server.c master_vars.c \ - master_wakeup.c + master_wakeup.c master_flow.c mail_flow.c OBJS = master.o master_conf.o master_ent.o master_sig.o master_avail.o \ master_spawn.o master_service.o master_status.o master_listen.o \ - master_vars.o master_wakeup.o -LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o -HDRS = mail_server.h master_proto.h + master_vars.o master_wakeup.o master_flow.o +LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \ + mail_flow.o +HDRS = mail_server.h master_proto.h mail_flow.h INT_HDR = master.h WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ @@ -78,6 +79,11 @@ depend: $(MAKES) @$(EXPORT) make -f Makefile.in Makefile 1>&2 # do not edit below this line - it is generated by 'make depend' +mail_flow.o: mail_flow.c +mail_flow.o: ../../include/sys_defs.h +mail_flow.o: ../../include/msg.h +mail_flow.o: mail_flow.h +mail_flow.o: master_proto.h master.o: master.c master.o: ../../include/sys_defs.h master.o: ../../include/events.h @@ -129,6 +135,12 @@ master_ent.o: ../../include/mail_params.h master_ent.o: ../../include/own_inet_addr.h master_ent.o: master_proto.h master_ent.o: master.h +master_flow.o: master_flow.c +master_flow.o: ../../include/sys_defs.h +master_flow.o: ../../include/msg.h +master_flow.o: ../../include/iostuff.h +master_flow.o: master.h +master_flow.o: master_proto.h master_listen.o: master_listen.c master_listen.o: ../../include/sys_defs.h master_listen.o: ../../include/msg.h diff --git a/postfix/src/master/mail_flow.c b/postfix/src/master/mail_flow.c new file mode 100644 index 000000000..5fc129216 --- /dev/null +++ b/postfix/src/master/mail_flow.c @@ -0,0 +1,112 @@ +/*++ +/* NAME +/* mail_flow 3 +/* SUMMARY +/* global mail flow control +/* SYNOPSIS +/* #include +/* +/* int mail_flow_get(count) +/* int count; +/* +/* void mail_flow_put(count) +/* int count; +/* DESCRIPTION +/* This module implements a simple flow control mechanism that +/* is based on tokens that are consumed by mail receiving processes +/* and that are produced by mail sending processes. +/* +/* mail_flow_get() attempts to read specified number of tokens. The +/* result is > 0 for success, < 0 for failure. In the latter case, +/* the process is expected to slow down a little. +/* +/* mail_flow_put() produces the specified number of tokens. The +/* token producing process is expected to produce new tokens +/* whenever it falls idle and no more tokens are available. +/* BUGS +/* The producer needs to wake up periodically to ensure that +/* tokens are not lost due to leakage. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include + +/* Global library. */ + +#include + +/* Master library. */ + +#include + +#define BUFFER_SIZE 1024 + +/* mail_flow_get - read N tokens */ + +int mail_flow_get(int len) +{ + char *myname = "mail_flow_get"; + char buf[BUFFER_SIZE]; + int count; + int n = 0; + + /* + * Sanity check. + */ + if (len <= 0) + msg_panic("%s: bad length %d", myname, len); + + /* + * Read and discard N bytes. + */ + for (count = len; count > 0; count -= n) + if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ? + BUFFER_SIZE : count)) < 0) + return (-1); + if (msg_verbose) + msg_info("%s: %d %d", myname, len, len - count); + return (len - count); +} + +/* mail_flow_put - put N tokens */ + +int mail_flow_put(int len) +{ + char *myname = "mail_flow_put"; + char buf[BUFFER_SIZE]; + int count; + int n = 0; + + /* + * Sanity check. + */ + if (len <= 0) + msg_panic("%s: bad length %d", myname, len); + + /* + * Read and discard N bytes. + */ + for (count = len; count > 0; count -= n) + if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ? + BUFFER_SIZE : count)) < 0) + return (-1); + if (msg_verbose) + msg_info("%s: %d %d", myname, len, len - count); + return (len - count); +} diff --git a/postfix/src/master/mail_flow.h b/postfix/src/master/mail_flow.h new file mode 100644 index 000000000..c146d83be --- /dev/null +++ b/postfix/src/master/mail_flow.h @@ -0,0 +1,31 @@ +#ifndef _MAIL_FLOW_H_INCLUDED_ +#define _MAIL_FLOW_H_INCLUDED_ + +/*++ +/* NAME +/* mail_flow 3h +/* SUMMARY +/* global mail flow control +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Functional interface. + */ +extern int mail_flow_get(int); +extern int mail_flow_put(int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/master/mail_server.h b/postfix/src/master/mail_server.h index d03313b1e..6c55603c1 100644 --- a/postfix/src/master/mail_server.h +++ b/postfix/src/master/mail_server.h @@ -28,6 +28,8 @@ #define MAIL_SERVER_EXIT 13 #define MAIL_SERVER_PRE_ACCEPT 14 +#define MAIL_SERVER_FLOW_CTL 20 + typedef void (*MAIL_SERVER_INIT_FN) (char *, char **); typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **); typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **); diff --git a/postfix/src/master/master.c b/postfix/src/master/master.c index 4299424f1..ad5af3b17 100644 --- a/postfix/src/master/master.c +++ b/postfix/src/master/master.c @@ -256,8 +256,11 @@ int main(int argc, char **argv) * when a service listens on many ports. In order to do this right we * must change the master-child interface so that descriptors do not need * to have fixed numbers. + * + * In a child we need two descriptors for the flow control pipe, one for + * child->master status updates and at least one for listening. */ - for (n = 0; n < 3; n++) { + for (n = 0; n < 5; n++) { if (close_on_exec(dup(0), CLOSE_ON_EXEC) < 0) msg_fatal("dup(0): %m"); } @@ -349,6 +352,7 @@ int main(int argc, char **argv) */ master_config(); master_sigsetup(); + master_flow_init(); msg_info("daemon started"); /* diff --git a/postfix/src/master/master.h b/postfix/src/master/master.h index abdfecc72..d2e472861 100644 --- a/postfix/src/master/master.h +++ b/postfix/src/master/master.h @@ -162,6 +162,12 @@ extern void master_spawn(MASTER_SERV *); extern void master_reap_child(void); extern void master_delete_children(MASTER_SERV *); + /* + * master_flow.c + */ +void master_flow_init(void); +int master_flow_pipe[2]; + /* DIAGNOSTICS /* BUGS /* SEE ALSO diff --git a/postfix/src/master/master_flow.c b/postfix/src/master/master_flow.c new file mode 100644 index 000000000..cc13f8cc8 --- /dev/null +++ b/postfix/src/master/master_flow.c @@ -0,0 +1,30 @@ +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include +#include + +/* Application-specific. */ + +#include +#include + +int master_flow_pipe[2]; + +/* master_flow_init - initialize the flow control channel */ + +void master_flow_init(void) +{ + char *myname = "master_flow_init"; + + if (pipe(master_flow_pipe) < 0) + msg_fatal("%s: pipe: %m", myname); + + non_blocking(master_flow_pipe[0], NON_BLOCKING); + non_blocking(master_flow_pipe[1], NON_BLOCKING); +} diff --git a/postfix/src/master/master_proto.h b/postfix/src/master/master_proto.h index 2929ed463..36c30f8d5 100644 --- a/postfix/src/master/master_proto.h +++ b/postfix/src/master/master_proto.h @@ -31,6 +31,14 @@ typedef struct MASTER_STATUS { extern int master_notify(int, int); /* encapsulate status msg */ + /* + * File descriptors inherited from the master process. The flow control pipe + * is read by receive processes and is written to by send processes. If + * receive processes get too far ahead they will pause for a brief moment. + */ +#define MASTER_FLOW_READ 3 +#define MASTER_FLOW_WRITE 4 + /* * File descriptors inherited from the master process. All processes that * provide a given service share the same status file descriptor, and listen @@ -41,8 +49,8 @@ extern int master_notify(int, int); /* encapsulate status msg */ * actually the lowest-numbered descriptor of a sequence of descriptors to * listen on. */ -#define MASTER_STATUS_FD 3 /* shared channel to parent */ -#define MASTER_LISTEN_FD 4 /* accept connections here */ +#define MASTER_STATUS_FD 5 /* shared channel to parent */ +#define MASTER_LISTEN_FD 6 /* accept connections here */ /* LICENSE /* .ad diff --git a/postfix/src/master/master_spawn.c b/postfix/src/master/master_spawn.c index 75dcfafbe..2eaf7bf96 100644 --- a/postfix/src/master/master_spawn.c +++ b/postfix/src/master/master_spawn.c @@ -175,6 +175,23 @@ void master_spawn(MASTER_SERV *serv) case 0: msg_cleanup((void (*) (void)) 0); /* disable exit handler */ closelog(); /* avoid filedes leak */ + + if (master_flow_pipe[0] <= MASTER_FLOW_READ) + msg_fatal("%s: flow pipe read descriptor <= %d", + myname, MASTER_FLOW_READ); + if (DUP2(master_flow_pipe[0], MASTER_FLOW_READ) < 0) + msg_fatal("%s: dup2: %m", myname); + if (close(master_flow_pipe[0]) < 0) + msg_fatal("close %d: %m", master_flow_pipe[0]); + + if (master_flow_pipe[1] <= MASTER_FLOW_WRITE) + msg_fatal("%s: flow pipe read descriptor <= %d", + myname, MASTER_FLOW_WRITE); + if (DUP2(master_flow_pipe[1], MASTER_FLOW_WRITE) < 0) + msg_fatal("%s: dup2: %m", myname); + if (close(master_flow_pipe[1]) < 0) + msg_fatal("close %d: %m", master_flow_pipe[1]); + close(serv->status_fd[0]); /* status channel */ if (serv->status_fd[1] <= MASTER_STATUS_FD) msg_fatal("%s: status file descriptor collision", myname); diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index c9df296f4..e845ca5ff 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -611,6 +611,8 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) } event_enable_read(MASTER_STATUS_FD, multi_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC); watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0); /* diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 9c6920a7d..58cc6f7ce 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -162,6 +162,7 @@ #include #include #include +#include /* Process manager. */ @@ -183,6 +184,7 @@ static void (*single_server_accept) (int, char *); static void (*single_server_onexit) (char *, char **); static void (*single_server_pre_accept) (char *, char **); static VSTREAM *single_server_lock; +static int single_server_flow_ctl; /* single_server_exit - normal termination */ @@ -238,6 +240,9 @@ static void single_server_wakeup(int fd) if (msg_verbose) msg_info("connection closed"); use_count++; + if (single_server_flow_ctl) + if (mail_flow_get(1) < 0) + rand_sleep(single_server_flow_ctl, 0); if (var_idle_limit > 0) event_request_timer(single_server_timeout, (char *) 0, var_idle_limit); } @@ -469,6 +474,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) case MAIL_SERVER_PRE_ACCEPT: single_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN); break; + case MAIL_SERVER_FLOW_CTL: + single_server_flow_ctl = var_glob_flow_ctl; + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } @@ -582,6 +590,8 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) } event_enable_read(MASTER_STATUS_FD, single_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC); watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0); /* diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index 7edd05ff6..61307e2a4 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -593,6 +593,8 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. } event_enable_read(MASTER_STATUS_FD, trigger_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC); watchdog = watchdog_create(1000, (WATCHDOG_FN) 0, (char *) 0); /* diff --git a/postfix/src/nqmgr/qmgr.c b/postfix/src/nqmgr/qmgr.c index 030c82d2d..c8c7f8685 100644 --- a/postfix/src/nqmgr/qmgr.c +++ b/postfix/src/nqmgr/qmgr.c @@ -298,6 +298,7 @@ #include #include #include /* QMGR_SCAN constants */ +#include /* Master process interface */ @@ -448,6 +449,17 @@ static int qmgr_loop(char *unused_name, char **unused_argv) if (qmgr_message_count < var_qmgr_active_limit) if ((df_path = qmgr_scan_next(qmgr_deferred)) != 0) qmgr_active_feed(qmgr_deferred, df_path); + + /* + * Global flow control. If enabled, slow down receiving processes that + * get ahead of the queue manager, but don't block them completely. + */ + if (var_glob_flow_ctl) { + if (in_path) + mail_flow_put(1); + else + mail_flow_get(1000); + } if (in_path || df_path) return (DONT_WAIT); return (WAIT_FOR_EVENT); diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 221254809..c2bbbbde6 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -90,9 +90,6 @@ /* \fBpostalias\fR terminates with zero exit status in case of success /* (including successful \fBpostmap -q\fR lookup) and terminates /* with non-zero exit status in case of failure. -/* BUGS -/* The "delete key" support is limited to one delete operation -/* per command invocation. /* ENVIRONMENT /* .ad /* .fi diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index aac5b1f69..a22ea3321 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -107,9 +107,6 @@ /* \fBpostmap\fR terminates with zero exit status in case of success /* (including successful \fBpostmap -q\fR lookup) and terminates /* with non-zero exit status in case of failure. -/* BUGS -/* The "delete key" support is limited to one delete operation -/* per command invocation. /* ENVIRONMENT /* .ad /* .fi diff --git a/postfix/src/qmgr/qmgr.c b/postfix/src/qmgr/qmgr.c index 7513aa368..0ce592ece 100644 --- a/postfix/src/qmgr/qmgr.c +++ b/postfix/src/qmgr/qmgr.c @@ -262,6 +262,7 @@ #include #include #include /* QMGR_SCAN constants */ +#include /* Master process interface */ @@ -410,6 +411,17 @@ static int qmgr_loop(char *unused_name, char **unused_argv) && qmgr_recipient_count < var_qmgr_rcpt_limit) if ((df_path = qmgr_scan_next(qmgr_deferred)) != 0) qmgr_active_feed(qmgr_deferred, df_path); + + /* + * Global flow control. If enabled, slow down receiving processes that + * get ahead of the queue manager, but don't block them completely. + */ + if (var_glob_flow_ctl) { + if (in_path) + mail_flow_put(1); + else + mail_flow_get(1000); + } if (in_path || df_path) return (DONT_WAIT); return (WAIT_FOR_EVENT);