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