1/*++ 2/* NAME 3/* master_avail 3 4/* SUMMARY 5/* Postfix master - process creation policy 6/* SYNOPSIS 7/* #include "master.h" 8/* 9/* void master_avail_listen(serv) 10/* MASTER_SERV *serv; 11/* 12/* void master_avail_cleanup(serv) 13/* MASTER_SERV *serv; 14/* 15/* void master_avail_more(serv, proc) 16/* MASTER_SERV *serv; 17/* MASTER_PROC *proc; 18/* 19/* void master_avail_less(serv, proc) 20/* MASTER_SERV *serv; 21/* MASTER_PROC *proc; 22/* DESCRIPTION 23/* This module implements the process creation policy. As long as 24/* the allowed number of processes for the given service is not 25/* exceeded, a connection request is either handled by an existing 26/* available process, or this module causes a new process to be 27/* created to service the request. 28/* 29/* When the service runs out of process slots, and the service 30/* is eligible for stress-mode operation, a warning is logged, 31/* servers are asked to restart at their convenience, and new 32/* servers are created with stress mode enabled. 33/* 34/* master_avail_listen() ensures that someone monitors the service's 35/* listen socket for connection requests (as long as resources 36/* to handle connection requests are available). This function may 37/* be called at random times, but it must be called after each status 38/* change of a service (throttled, process limit, etc.) or child 39/* process (taken, available, dead, etc.). 40/* 41/* master_avail_cleanup() should be called when the named service 42/* is taken out of operation. It terminates child processes by 43/* sending SIGTERM. 44/* 45/* master_avail_more() should be called when the named process 46/* has become available for servicing new connection requests. 47/* This function updates the process availability status and 48/* counter, and implicitly calls master_avail_listen(). 49/* 50/* master_avail_less() should be called when the named process 51/* has become unavailable for servicing new connection requests. 52/* This function updates the process availability status and 53/* counter, and implicitly calls master_avail_listen(). 54/* DIAGNOSTICS 55/* Panic: internal inconsistencies. 56/* BUGS 57/* SEE ALSO 58/* master_spawn(3), child process birth and death 59/* LICENSE 60/* .ad 61/* .fi 62/* The Secure Mailer license must be distributed with this software. 63/* AUTHOR(S) 64/* Wietse Venema 65/* IBM T.J. Watson Research 66/* P.O. Box 704 67/* Yorktown Heights, NY 10598, USA 68/*--*/ 69 70/* System libraries. */ 71 72#include <sys_defs.h> 73 74/* Utility library. */ 75 76#include <events.h> 77#include <msg.h> 78 79/* Application-specific. */ 80 81#include "master_proto.h" 82#include "master.h" 83 84/* master_avail_event - create child process to handle connection request */ 85 86static void master_avail_event(int event, char *context) 87{ 88 MASTER_SERV *serv = (MASTER_SERV *) context; 89 time_t now; 90 91 if (event == 0) /* XXX Can this happen? */ 92 msg_panic("master_avail_event: null event"); 93 else { 94 95 /* 96 * When all servers for a public internet service are busy, we start 97 * creating server processes with "-o stress=yes" on the command 98 * line, and keep creating such processes until the process count is 99 * below the limit for at least 1000 seconds. This provides a minimal 100 * solution that can be adopted into legacy and stable Postfix 101 * releases. 102 * 103 * This is not the right place to update serv->stress_param_val in 104 * response to stress level changes. Doing so would would contaminate 105 * the "postfix reload" code with stress management implementation 106 * details, creating a source of future bugs. Instead, we update 107 * simple counters or flags here, and use their values to determine 108 * the proper serv->stress_param_val value when exec-ing a server 109 * process. 110 */ 111 if (serv->stress_param_val != 0 112 && !MASTER_LIMIT_OK(serv->max_proc, serv->total_proc + 1)) { 113 now = event_time(); 114 if (serv->stress_expire_time < now) 115 master_restart_service(serv, NO_CONF_RELOAD); 116 serv->stress_expire_time = now + 1000; 117 } 118 master_spawn(serv); 119 } 120} 121 122/* master_avail_listen - enforce the socket monitoring policy */ 123 124void master_avail_listen(MASTER_SERV *serv) 125{ 126 const char *myname = "master_avail_listen"; 127 int listen_flag; 128 time_t now; 129 int n; 130 131 /* 132 * Caution: several other master_XXX modules call master_avail_listen(), 133 * master_avail_more() or master_avail_less(). To avoid mutual dependency 134 * problems, the code below invokes no code in other master_XXX modules, 135 * and modifies no data that is maintained by other master_XXX modules. 136 * 137 * When no-one else is monitoring the service's listen socket, start 138 * monitoring the socket for connection requests. All this under the 139 * restriction that we have sufficient resources to service a connection 140 * request. 141 */ 142 if (msg_verbose) 143 msg_info("%s: %s avail %d total %d max %d", myname, serv->name, 144 serv->avail_proc, serv->total_proc, serv->max_proc); 145 if (MASTER_THROTTLED(serv) || serv->avail_proc > 0) { 146 listen_flag = 0; 147 } else if (MASTER_LIMIT_OK(serv->max_proc, serv->total_proc)) { 148 listen_flag = 1; 149 } else { 150 listen_flag = 0; 151 if (serv->stress_param_val != 0) { 152 now = event_time(); 153 if (serv->busy_warn_time < now - 1000) { 154 serv->busy_warn_time = now; 155 msg_warn("service \"%s\" (%s) has reached its process limit \"%d\": " 156 "new clients may experience noticeable delays", 157 serv->ext_name, serv->name, serv->max_proc); 158 msg_warn("to avoid this condition, increase the process count " 159 "in master.cf or reduce the service time per client"); 160 msg_warn("see http://www.postfix.org/STRESS_README.html for " 161 "examples of stress-adapting configuration settings"); 162 } 163 } 164 } 165 if (listen_flag && !MASTER_LISTENING(serv)) { 166 if (msg_verbose) 167 msg_info("%s: enable events %s", myname, serv->name); 168 for (n = 0; n < serv->listen_fd_count; n++) 169 event_enable_read(serv->listen_fd[n], master_avail_event, 170 (char *) serv); 171 serv->flags |= MASTER_FLAG_LISTEN; 172 } else if (!listen_flag && MASTER_LISTENING(serv)) { 173 if (msg_verbose) 174 msg_info("%s: disable events %s", myname, serv->name); 175 for (n = 0; n < serv->listen_fd_count; n++) 176 event_disable_readwrite(serv->listen_fd[n]); 177 serv->flags &= ~MASTER_FLAG_LISTEN; 178 } 179} 180 181/* master_avail_cleanup - cleanup */ 182 183void master_avail_cleanup(MASTER_SERV *serv) 184{ 185 int n; 186 187 master_delete_children(serv); /* XXX calls 188 * master_avail_listen */ 189 190 /* 191 * This code is redundant because master_delete_children() throttles the 192 * service temporarily before calling master_avail_listen/less(), which 193 * then turn off read events. This temporary throttling is not documented 194 * (it is only an optimization), and therefore we must not depend on it. 195 */ 196 if (MASTER_LISTENING(serv)) { 197 for (n = 0; n < serv->listen_fd_count; n++) 198 event_disable_readwrite(serv->listen_fd[n]); 199 serv->flags &= ~MASTER_FLAG_LISTEN; 200 } 201} 202 203/* master_avail_more - one more available child process */ 204 205void master_avail_more(MASTER_SERV *serv, MASTER_PROC *proc) 206{ 207 const char *myname = "master_avail_more"; 208 209 /* 210 * Caution: several other master_XXX modules call master_avail_listen(), 211 * master_avail_more() or master_avail_less(). To avoid mutual dependency 212 * problems, the code below invokes no code in other master_XXX modules, 213 * and modifies no data that is maintained by other master_XXX modules. 214 * 215 * This child process has become available for servicing connection 216 * requests, so we can stop monitoring the service's listen socket. The 217 * child will do it for us. 218 */ 219 if (msg_verbose) 220 msg_info("%s: pid %d (%s)", myname, proc->pid, proc->serv->name); 221 if (proc->avail == MASTER_STAT_AVAIL) 222 msg_panic("%s: process already available", myname); 223 serv->avail_proc++; 224 proc->avail = MASTER_STAT_AVAIL; 225 master_avail_listen(serv); 226} 227 228/* master_avail_less - one less available child process */ 229 230void master_avail_less(MASTER_SERV *serv, MASTER_PROC *proc) 231{ 232 const char *myname = "master_avail_less"; 233 234 /* 235 * Caution: several other master_XXX modules call master_avail_listen(), 236 * master_avail_more() or master_avail_less(). To avoid mutual dependency 237 * problems, the code below invokes no code in other master_XXX modules, 238 * and modifies no data that is maintained by other master_XXX modules. 239 * 240 * This child is no longer available for servicing connection requests. 241 * When no child processes are available, start monitoring the service's 242 * listen socket for new connection requests. 243 */ 244 if (msg_verbose) 245 msg_info("%s: pid %d (%s)", myname, proc->pid, proc->serv->name); 246 if (proc->avail != MASTER_STAT_AVAIL) 247 msg_panic("%s: process not available", myname); 248 serv->avail_proc--; 249 proc->avail = MASTER_STAT_TAKEN; 250 master_avail_listen(serv); 251} 252