Postfix3.3.1
master_avail.c
[詳解]
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 
86 static void master_avail_event(int event, void *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)
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 
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  (void *) 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++)
177  serv->flags &= ~MASTER_FLAG_LISTEN;
178  }
179 }
180 
181 /* master_avail_cleanup - cleanup */
182 
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++)
199  serv->flags &= ~MASTER_FLAG_LISTEN;
200  }
201 }
202 
203 /* master_avail_more - one more available child process */
204 
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 
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. When
241  * 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 }
int msg_verbose
Definition: msg.c:177
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
Definition: events.c:729
#define MASTER_LIMIT_OK(limit, count)
Definition: master.h:73
int listen_fd_count
Definition: master.h:35
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define MASTER_LISTENING(f)
Definition: master.h:71
#define MASTER_FLAG_LISTEN
Definition: master.h:67
#define MASTER_STAT_AVAIL
Definition: master_proto.h:34
void master_avail_more(MASTER_SERV *serv, MASTER_PROC *proc)
Definition: master_avail.c:205
char * ext_name
Definition: master.h:29
void master_restart_service(MASTER_SERV *, int)
int total_proc
Definition: master.h:50
void master_avail_listen(MASTER_SERV *serv)
Definition: master_avail.c:124
char * name
Definition: master.h:30
#define MASTER_THROTTLED(f)
Definition: master.h:69
char * stress_param_val
Definition: master.h:47
time_t busy_warn_time
Definition: master.h:32
int avail_proc
Definition: master.h:49
#define MASTER_STAT_TAKEN
Definition: master_proto.h:33
MASTER_SERV * serv
Definition: master.h:99
int flags
Definition: master.h:28
void msg_warn(const char *fmt,...)
Definition: msg.c:215
void master_avail_less(MASTER_SERV *serv, MASTER_PROC *proc)
Definition: master_avail.c:230
time_t stress_expire_time
Definition: master.h:48
void master_delete_children(MASTER_SERV *)
Definition: master_spawn.c:347
void master_avail_cleanup(MASTER_SERV *serv)
Definition: master_avail.c:183
time_t event_time(void)
Definition: events.c:647
int max_proc
Definition: master.h:44
MASTER_PID pid
Definition: master.h:96
void master_spawn(MASTER_SERV *)
Definition: master_spawn.c:139
#define NO_CONF_RELOAD
Definition: master.h:144
int * listen_fd
Definition: master.h:34
void event_disable_readwrite(int fd)
Definition: events.c:839
int avail
Definition: master.h:98
void msg_info(const char *fmt,...)
Definition: msg.c:199