Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/master/login-process.c @ 1055:a72bba3f8a55 HEAD
Rewrote setting handling. Changed some existing settings also since POP3
support required changes anyway. POP3 seems to be really working now :)
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 30 Jan 2003 19:59:31 +0200 |
parents | 793f05a7e50e |
children | 6cb5b50aea71 |
comparison
equal
deleted
inserted
replaced
1054:cd1ac4101adf | 1055:a72bba3f8a55 |
---|---|
9 #include "env-util.h" | 9 #include "env-util.h" |
10 #include "restrict-access.h" | 10 #include "restrict-access.h" |
11 #include "restrict-process-size.h" | 11 #include "restrict-process-size.h" |
12 #include "login-process.h" | 12 #include "login-process.h" |
13 #include "auth-process.h" | 13 #include "auth-process.h" |
14 #include "imap-process.h" | 14 #include "mail-process.h" |
15 #include "master-login-interface.h" | 15 #include "master-login-interface.h" |
16 | 16 |
17 #include <unistd.h> | 17 #include <unistd.h> |
18 #include <syslog.h> | 18 #include <syslog.h> |
19 | 19 |
20 struct login_group { | |
21 struct login_group *next; | |
22 | |
23 struct login_settings *set; | |
24 | |
25 unsigned int processes; | |
26 unsigned int listening_processes; | |
27 unsigned int wanted_processes_count; | |
28 | |
29 struct login_process *oldest_nonlisten_process; | |
30 struct login_process *newest_nonlisten_process; | |
31 | |
32 const char *executable; | |
33 unsigned int process_size; | |
34 int *listen_fd, *ssl_listen_fd; | |
35 }; | |
36 | |
20 struct login_process { | 37 struct login_process { |
38 struct login_group *group; | |
21 struct login_process *prev_nonlisten, *next_nonlisten; | 39 struct login_process *prev_nonlisten, *next_nonlisten; |
22 int refcount; | 40 int refcount; |
23 | 41 |
24 pid_t pid; | 42 pid_t pid; |
25 int fd; | 43 int fd; |
42 | 60 |
43 static unsigned int auth_id_counter; | 61 static unsigned int auth_id_counter; |
44 static struct timeout *to; | 62 static struct timeout *to; |
45 | 63 |
46 static struct hash_table *processes; | 64 static struct hash_table *processes; |
47 static struct login_process *oldest_nonlisten_process; | 65 static struct login_group *login_groups; |
48 static struct login_process *newest_nonlisten_process; | |
49 static unsigned int listening_processes; | |
50 static unsigned int wanted_processes_count; | |
51 | 66 |
52 static void login_process_destroy(struct login_process *p); | 67 static void login_process_destroy(struct login_process *p); |
53 static void login_process_unref(struct login_process *p); | 68 static void login_process_unref(struct login_process *p); |
69 | |
70 static void login_group_create(struct login_settings *login_set) | |
71 { | |
72 struct login_group *group; | |
73 | |
74 group = i_new(struct login_group, 1); | |
75 group->set = login_set; | |
76 | |
77 if (strcmp(login_set->name, "imap") == 0) { | |
78 group->executable = set->imap_executable; | |
79 group->process_size = set->imap_process_size; | |
80 group->listen_fd = &mail_fd[FD_IMAP]; | |
81 group->ssl_listen_fd = &mail_fd[FD_IMAPS]; | |
82 } else if (strcmp(login_set->name, "pop3") == 0) { | |
83 group->executable = set->pop3_executable; | |
84 group->process_size = set->pop3_process_size; | |
85 group->listen_fd = &mail_fd[FD_POP3]; | |
86 group->ssl_listen_fd = &mail_fd[FD_POP3S]; | |
87 } else | |
88 i_panic("Unknown login group name '%s'", login_set->name); | |
89 | |
90 group->next = login_groups; | |
91 login_groups = group; | |
92 } | |
93 | |
94 static void login_group_destroy(struct login_group *group) | |
95 { | |
96 i_free(group); | |
97 } | |
54 | 98 |
55 void auth_master_callback(struct auth_master_reply *reply, | 99 void auth_master_callback(struct auth_master_reply *reply, |
56 const unsigned char *data, void *context) | 100 const unsigned char *data, void *context) |
57 { | 101 { |
58 struct login_auth_request *request = context; | 102 struct login_auth_request *request = context; |
59 struct master_login_reply master_reply; | 103 struct master_login_reply master_reply; |
60 | 104 |
61 if (reply == NULL || !reply->success) | 105 if (reply == NULL || !reply->success) |
62 master_reply.success = FALSE; | 106 master_reply.success = FALSE; |
63 else { | 107 else { |
108 struct login_group *group = request->process->group; | |
109 | |
64 master_reply.success = | 110 master_reply.success = |
65 create_imap_process(request->fd, &request->ip, reply, | 111 create_mail_process(request->fd, &request->ip, |
66 (const char *) data); | 112 group->executable, |
113 group->process_size, | |
114 reply, (const char *) data); | |
67 } | 115 } |
68 | 116 |
69 /* reply to login */ | 117 /* reply to login */ |
70 master_reply.tag = request->login_tag; | 118 master_reply.tag = request->login_tag; |
71 | 119 |
72 if (o_stream_send(request->process->output, &master_reply, | 120 if (o_stream_send(request->process->output, &master_reply, |
73 sizeof(master_reply)) < 0) | 121 sizeof(master_reply)) < 0) |
74 login_process_destroy(request->process); | 122 login_process_destroy(request->process); |
75 | 123 |
76 if (close(request->fd) < 0) | 124 if (close(request->fd) < 0) |
77 i_error("close(imap client) failed: %m"); | 125 i_error("close(mail client) failed: %m"); |
78 login_process_unref(request->process); | 126 login_process_unref(request->process); |
79 i_free(request); | 127 i_free(request); |
80 } | 128 } |
81 | 129 |
82 static void login_process_mark_nonlistening(struct login_process *p) | 130 static void login_process_mark_nonlistening(struct login_process *p) |
86 "notification"); | 134 "notification"); |
87 return; | 135 return; |
88 } | 136 } |
89 | 137 |
90 p->listening = FALSE; | 138 p->listening = FALSE; |
91 listening_processes--; | 139 p->group->listening_processes--; |
92 | 140 |
93 p->prev_nonlisten = newest_nonlisten_process; | 141 p->prev_nonlisten = p->group->newest_nonlisten_process; |
94 | 142 |
95 if (newest_nonlisten_process != NULL) | 143 if (p->group->newest_nonlisten_process != NULL) |
96 newest_nonlisten_process->next_nonlisten = p; | 144 p->group->newest_nonlisten_process->next_nonlisten = p; |
97 newest_nonlisten_process = p; | 145 p->group->newest_nonlisten_process = p; |
98 | 146 |
99 if (oldest_nonlisten_process == NULL) | 147 if (p->group->oldest_nonlisten_process == NULL) |
100 oldest_nonlisten_process = p; | 148 p->group->oldest_nonlisten_process = p; |
101 } | 149 } |
102 | 150 |
103 static void login_process_input(void *context) | 151 static void login_process_input(void *context) |
104 { | 152 { |
105 struct login_process *p = context; | 153 struct login_process *p = context; |
119 i_error("login: fd_read() failed: %m"); | 167 i_error("login: fd_read() failed: %m"); |
120 } | 168 } |
121 | 169 |
122 if (client_fd != -1) { | 170 if (client_fd != -1) { |
123 if (close(client_fd) < 0) | 171 if (close(client_fd) < 0) |
124 i_error("close(imap client) failed: %m"); | 172 i_error("close(mail client) failed: %m"); |
125 } | 173 } |
126 | 174 |
127 login_process_destroy(p); | 175 login_process_destroy(p); |
128 return; | 176 return; |
129 } | 177 } |
160 auth_process_request(auth_process, p->pid, | 208 auth_process_request(auth_process, p->pid, |
161 req.auth_id, authreq); | 209 req.auth_id, authreq); |
162 } | 210 } |
163 } | 211 } |
164 | 212 |
165 static struct login_process *login_process_new(pid_t pid, int fd) | 213 static struct login_process * |
214 login_process_new(struct login_group *group, pid_t pid, int fd) | |
166 { | 215 { |
167 struct login_process *p; | 216 struct login_process *p; |
168 | 217 |
169 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); | 218 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); |
170 | 219 |
171 p = i_new(struct login_process, 1); | 220 p = i_new(struct login_process, 1); |
221 p->group = group; | |
172 p->refcount = 1; | 222 p->refcount = 1; |
173 p->pid = pid; | 223 p->pid = pid; |
174 p->fd = fd; | 224 p->fd = fd; |
175 p->listening = TRUE; | 225 p->listening = TRUE; |
176 p->io = io_add(fd, IO_READ, login_process_input, p); | 226 p->io = io_add(fd, IO_READ, login_process_input, p); |
177 p->output = o_stream_create_file(fd, default_pool, | 227 p->output = o_stream_create_file(fd, default_pool, |
178 sizeof(struct master_login_reply)*10, | 228 sizeof(struct master_login_reply)*10, |
179 IO_PRIORITY_DEFAULT, FALSE); | 229 IO_PRIORITY_DEFAULT, FALSE); |
180 | 230 |
181 hash_insert(processes, POINTER_CAST(pid), p); | 231 hash_insert(processes, POINTER_CAST(pid), p); |
182 listening_processes++; | 232 p->group->processes++; |
233 p->group->listening_processes++; | |
183 return p; | 234 return p; |
184 } | 235 } |
185 | 236 |
186 static void login_process_remove_from_lists(struct login_process *p) | 237 static void login_process_remove_from_lists(struct login_process *p) |
187 { | 238 { |
188 if (p == oldest_nonlisten_process) | 239 if (p == p->group->oldest_nonlisten_process) |
189 oldest_nonlisten_process = p->next_nonlisten; | 240 p->group->oldest_nonlisten_process = p->next_nonlisten; |
190 else | 241 else |
191 p->prev_nonlisten->next_nonlisten = p->next_nonlisten; | 242 p->prev_nonlisten->next_nonlisten = p->next_nonlisten; |
192 | 243 |
193 if (p == newest_nonlisten_process) | 244 if (p == p->group->newest_nonlisten_process) |
194 newest_nonlisten_process = p->prev_nonlisten; | 245 p->group->newest_nonlisten_process = p->prev_nonlisten; |
195 else | 246 else |
196 p->next_nonlisten->prev_nonlisten = p->prev_nonlisten; | 247 p->next_nonlisten->prev_nonlisten = p->prev_nonlisten; |
197 | 248 |
198 p->next_nonlisten = p->prev_nonlisten = NULL; | 249 p->next_nonlisten = p->prev_nonlisten = NULL; |
199 } | 250 } |
207 if (!p->initialized && io_loop_is_running(ioloop)) { | 258 if (!p->initialized && io_loop_is_running(ioloop)) { |
208 i_error("Login process died too early - shutting down"); | 259 i_error("Login process died too early - shutting down"); |
209 io_loop_stop(ioloop); | 260 io_loop_stop(ioloop); |
210 } | 261 } |
211 if (p->listening) | 262 if (p->listening) |
212 listening_processes--; | 263 p->group->listening_processes--; |
213 | 264 |
214 o_stream_close(p->output); | 265 o_stream_close(p->output); |
215 io_remove(p->io); | 266 io_remove(p->io); |
216 if (close(p->fd) < 0) | 267 if (close(p->fd) < 0) |
217 i_error("close(login) failed: %m"); | 268 i_error("close(login) failed: %m"); |
218 | 269 |
219 if (!p->listening) | 270 if (!p->listening) |
220 login_process_remove_from_lists(p); | 271 login_process_remove_from_lists(p); |
221 | 272 |
273 p->group->processes--; | |
222 hash_remove(processes, POINTER_CAST(p->pid)); | 274 hash_remove(processes, POINTER_CAST(p->pid)); |
223 | 275 |
224 login_process_unref(p); | 276 login_process_unref(p); |
225 } | 277 } |
226 | 278 |
231 | 283 |
232 o_stream_unref(p->output); | 284 o_stream_unref(p->output); |
233 i_free(p); | 285 i_free(p); |
234 } | 286 } |
235 | 287 |
236 static pid_t create_login_process(void) | 288 static pid_t create_login_process(struct login_group *group) |
237 { | 289 { |
238 static char *argv[] = { NULL, NULL }; | 290 static const char *argv[] = { NULL, NULL }; |
239 pid_t pid; | 291 pid_t pid; |
240 int fd[2]; | 292 int fd[2]; |
241 | 293 |
242 if (set_login_process_per_connection && | 294 if (group->set->process_per_connection && |
243 hash_size(processes)-listening_processes >= set_max_logging_users) { | 295 group->processes - group->listening_processes >= |
244 if (oldest_nonlisten_process != NULL) | 296 group->set->max_logging_users) { |
245 login_process_destroy(oldest_nonlisten_process); | 297 if (group->oldest_nonlisten_process != NULL) |
246 } | 298 login_process_destroy(group->oldest_nonlisten_process); |
247 | 299 } |
248 if (set_login_uid == 0) | 300 |
301 if (group->set->uid == 0) | |
249 i_fatal("Login process must not run as root"); | 302 i_fatal("Login process must not run as root"); |
250 | 303 |
251 /* create communication to process with a socket pair */ | 304 /* create communication to process with a socket pair */ |
252 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { | 305 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { |
253 i_error("socketpair() failed: %m"); | 306 i_error("socketpair() failed: %m"); |
263 } | 316 } |
264 | 317 |
265 if (pid != 0) { | 318 if (pid != 0) { |
266 /* master */ | 319 /* master */ |
267 fd_close_on_exec(fd[0], TRUE); | 320 fd_close_on_exec(fd[0], TRUE); |
268 login_process_new(pid, fd[0]); | 321 login_process_new(group, pid, fd[0]); |
269 (void)close(fd[1]); | 322 (void)close(fd[1]); |
270 return pid; | 323 return pid; |
271 } | 324 } |
272 | 325 |
273 /* move communication handle */ | 326 /* move communication handle */ |
274 if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0) | 327 if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0) |
275 i_fatal("login: dup2(master) failed: %m"); | 328 i_fatal("login: dup2(master) failed: %m"); |
276 fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE); | 329 fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE); |
277 | 330 |
278 /* move the listen handle */ | 331 /* move the listen handle */ |
279 if (dup2(imap_fd, LOGIN_IMAP_LISTEN_FD) < 0) | 332 if (dup2(*group->listen_fd, LOGIN_LISTEN_FD) < 0) |
280 i_fatal("login: dup2(imap) failed: %m"); | 333 i_fatal("login: dup2(listen_fd) failed: %m"); |
281 fd_close_on_exec(LOGIN_IMAP_LISTEN_FD, FALSE); | 334 fd_close_on_exec(LOGIN_LISTEN_FD, FALSE); |
282 | 335 |
283 /* move the SSL listen handle */ | 336 /* move the SSL listen handle */ |
284 if (!set_ssl_disable) { | 337 if (!set->ssl_disable) { |
285 if (dup2(imaps_fd, LOGIN_IMAPS_LISTEN_FD) < 0) | 338 if (dup2(*group->ssl_listen_fd, LOGIN_SSL_LISTEN_FD) < 0) |
286 i_fatal("login: dup2(imaps) failed: %m"); | 339 i_fatal("login: dup2(ssl_listen_fd) failed: %m"); |
287 } else { | 340 } else { |
288 if (dup2(null_fd, LOGIN_IMAPS_LISTEN_FD) < 0) | 341 if (dup2(null_fd, LOGIN_SSL_LISTEN_FD) < 0) |
289 i_fatal("login: dup2(imaps) failed: %m"); | 342 i_fatal("login: dup2(ssl_listen_fd) failed: %m"); |
290 } | 343 } |
291 fd_close_on_exec(LOGIN_IMAPS_LISTEN_FD, FALSE); | 344 fd_close_on_exec(LOGIN_SSL_LISTEN_FD, FALSE); |
292 | 345 |
293 /* imap_fd and imaps_fd are closed by clean_child_process() */ | 346 /* listen_fds are closed by clean_child_process() */ |
294 | 347 |
295 (void)close(fd[0]); | 348 (void)close(fd[0]); |
296 (void)close(fd[1]); | 349 (void)close(fd[1]); |
297 | 350 |
298 clean_child_process(); | 351 clean_child_process(); |
299 | 352 |
300 /* setup access environment - needs to be done after | 353 /* setup access environment - needs to be done after |
301 clean_child_process() since it clears environment */ | 354 clean_child_process() since it clears environment */ |
302 restrict_access_set_env(set_login_user, set_login_uid, set_login_gid, | 355 restrict_access_set_env(group->set->user, |
303 set_login_chroot ? set_login_dir : NULL); | 356 group->set->uid, set->login_gid, |
304 | 357 set->login_chroot ? set->login_dir : NULL); |
305 if (!set_login_chroot) { | 358 |
359 if (!set->login_chroot) { | |
306 /* no chrooting, but still change to the directory */ | 360 /* no chrooting, but still change to the directory */ |
307 if (chdir(set_login_dir) < 0) | 361 if (chdir(set->login_dir) < 0) |
308 i_fatal("chdir(%s) failed: %m", set_login_dir); | 362 i_fatal("chdir(%s) failed: %m", set->login_dir); |
309 } | 363 } |
310 | 364 |
311 if (!set_ssl_disable) { | 365 if (!set->ssl_disable) { |
312 env_put(t_strconcat("SSL_CERT_FILE=", set_ssl_cert_file, NULL)); | 366 env_put(t_strconcat("SSL_CERT_FILE=", |
313 env_put(t_strconcat("SSL_KEY_FILE=", set_ssl_key_file, NULL)); | 367 set->ssl_cert_file, NULL)); |
368 env_put(t_strconcat("SSL_KEY_FILE=", set->ssl_key_file, NULL)); | |
314 env_put(t_strconcat("SSL_PARAM_FILE=", | 369 env_put(t_strconcat("SSL_PARAM_FILE=", |
315 set_ssl_parameters_file, NULL)); | 370 set->ssl_parameters_file, NULL)); |
316 } | 371 } |
317 | 372 |
318 if (set_disable_plaintext_auth) | 373 if (set->disable_plaintext_auth) |
319 env_put("DISABLE_PLAINTEXT_AUTH=1"); | 374 env_put("DISABLE_PLAINTEXT_AUTH=1"); |
320 if (set_verbose_proctitle) | 375 if (set->verbose_proctitle) |
321 env_put("VERBOSE_PROCTITLE=1"); | 376 env_put("VERBOSE_PROCTITLE=1"); |
322 | 377 |
323 if (set_login_process_per_connection) { | 378 if (group->set->process_per_connection) { |
324 env_put("PROCESS_PER_CONNECTION=1"); | 379 env_put("PROCESS_PER_CONNECTION=1"); |
325 env_put("MAX_LOGGING_USERS=1"); | 380 env_put("MAX_LOGGING_USERS=1"); |
326 } else { | 381 } else { |
327 env_put(t_strdup_printf("MAX_LOGGING_USERS=%u", | 382 env_put(t_strdup_printf("MAX_LOGGING_USERS=%u", |
328 set_max_logging_users)); | 383 group->set->max_logging_users)); |
329 } | 384 } |
330 | 385 |
331 env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(getpid()))); | 386 env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(getpid()))); |
332 | 387 |
333 restrict_process_size(set_login_process_size); | 388 restrict_process_size(group->set->process_size); |
334 | 389 |
335 /* make sure we don't leak syslog fd, but do it last so that | 390 /* make sure we don't leak syslog fd, but do it last so that |
336 any errors above will be logged */ | 391 any errors above will be logged */ |
337 closelog(); | 392 closelog(); |
338 | 393 |
339 /* hide the path, it's ugly */ | 394 /* hide the path, it's ugly */ |
340 argv[0] = strrchr(set_login_executable, '/'); | 395 argv[0] = strrchr(group->set->executable, '/'); |
341 if (argv[0] == NULL) argv[0] = set_login_executable; else argv[0]++; | 396 if (argv[0] == NULL) argv[0] = group->set->executable; else argv[0]++; |
342 | 397 |
343 execv(set_login_executable, (char **) argv); | 398 execv(group->set->executable, (char **) argv); |
344 | 399 |
345 i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", argv[0]); | 400 i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", argv[0]); |
346 return -1; | 401 return -1; |
347 } | 402 } |
348 | 403 |
349 void login_process_abormal_exit(pid_t pid __attr_unused__) | 404 void login_process_abormal_exit(pid_t pid) |
350 { | 405 { |
406 struct login_process *p; | |
407 | |
351 /* don't start raising the process count if they're dying all | 408 /* don't start raising the process count if they're dying all |
352 the time */ | 409 the time */ |
353 wanted_processes_count = 0; | 410 p = hash_lookup(processes, POINTER_CAST(pid)); |
411 if (p != NULL) | |
412 p->group->wanted_processes_count = 0; | |
354 } | 413 } |
355 | 414 |
356 static void login_hash_destroy(void *key __attr_unused__, void *value, | 415 static void login_hash_destroy(void *key __attr_unused__, void *value, |
357 void *context __attr_unused__) | 416 void *context __attr_unused__) |
358 { | 417 { |
361 | 420 |
362 void login_processes_destroy_all(void) | 421 void login_processes_destroy_all(void) |
363 { | 422 { |
364 hash_foreach(processes, login_hash_destroy, NULL); | 423 hash_foreach(processes, login_hash_destroy, NULL); |
365 | 424 |
366 /* don't double their amount when restarting */ | 425 while (login_groups != NULL) { |
367 wanted_processes_count = 0; | 426 struct login_group *group = login_groups; |
427 | |
428 login_groups = group->next; | |
429 login_group_destroy(group); | |
430 } | |
431 } | |
432 | |
433 static void login_group_start_missings(struct login_group *group) | |
434 { | |
435 if (!group->set->process_per_connection) { | |
436 /* create max. one process every second, that way if it keeps | |
437 dying all the time we don't eat all cpu with fork()ing. */ | |
438 if (group->listening_processes < group->set->processes_count) | |
439 (void)create_login_process(group); | |
440 return; | |
441 } | |
442 | |
443 /* we want to respond fast when multiple clients are connecting | |
444 at once, but we also want to prevent fork-bombing. use the | |
445 same method as apache: check once a second if we need new | |
446 processes. if yes and we've used all the existing processes, | |
447 double their amount (unless we've hit the high limit). | |
448 Then for each second that didn't use all existing processes, | |
449 drop the max. process count by one. */ | |
450 if (group->wanted_processes_count < group->set->processes_count) | |
451 group->wanted_processes_count = group->set->processes_count; | |
452 else if (group->listening_processes == 0) | |
453 group->wanted_processes_count *= 2; | |
454 else if (group->wanted_processes_count > group->set->processes_count) | |
455 group->wanted_processes_count--; | |
456 | |
457 if (group->wanted_processes_count > group->set->max_processes_count) | |
458 group->wanted_processes_count = group->set->max_processes_count; | |
459 | |
460 while (group->listening_processes < group->wanted_processes_count) | |
461 (void)create_login_process(group); | |
368 } | 462 } |
369 | 463 |
370 static void | 464 static void |
371 login_processes_start_missing(void *context __attr_unused__) | 465 login_processes_start_missing(void *context __attr_unused__) |
372 { | 466 { |
373 if (!set_login_process_per_connection) { | 467 struct login_group *group; |
374 /* create max. one process every second, that way if it keeps | 468 struct login_settings *login; |
375 dying all the time we don't eat all cpu with fork()ing. */ | 469 |
376 if (listening_processes < set_login_processes_count) | 470 if (login_groups == NULL) { |
377 (void)create_login_process(); | 471 for (login = set->logins; login != NULL; login = login->next) |
378 } else { | 472 login_group_create(login); |
379 /* we want to respond fast when multiple clients are connecting | 473 } |
380 at once, but we also want to prevent fork-bombing. use the | 474 |
381 same method as apache: check once a second if we need new | 475 for (group = login_groups; group != NULL; group = group->next) |
382 processes. if yes and we've used all the existing processes, | 476 login_group_start_missings(group); |
383 double their amount (unless we've hit the high limit). | |
384 Then for each second that didn't use all existing processes, | |
385 drop the max. process count by one. */ | |
386 if (wanted_processes_count < set_login_processes_count) | |
387 wanted_processes_count = set_login_processes_count; | |
388 else if (listening_processes == 0) | |
389 wanted_processes_count *= 2; | |
390 else if (wanted_processes_count > set_login_processes_count) | |
391 wanted_processes_count--; | |
392 | |
393 if (wanted_processes_count > set_login_max_processes_count) | |
394 wanted_processes_count = set_login_max_processes_count; | |
395 | |
396 while (listening_processes < wanted_processes_count) | |
397 (void)create_login_process(); | |
398 } | |
399 } | 477 } |
400 | 478 |
401 void login_processes_init(void) | 479 void login_processes_init(void) |
402 { | 480 { |
403 auth_id_counter = 0; | 481 auth_id_counter = 0; |
404 listening_processes = 0; | 482 login_groups = NULL; |
405 wanted_processes_count = 0; | |
406 oldest_nonlisten_process = newest_nonlisten_process = NULL; | |
407 | 483 |
408 processes = hash_create(default_pool, default_pool, 128, NULL, NULL); | 484 processes = hash_create(default_pool, default_pool, 128, NULL, NULL); |
409 to = timeout_add(1000, login_processes_start_missing, NULL); | 485 to = timeout_add(1000, login_processes_start_missing, NULL); |
410 } | 486 } |
411 | 487 |