Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/master/login-process.c @ 614:e60620644af3 HEAD
login_process_per_connection = yes scales now better when multiple users are
trying to log in at the same time.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 16 Nov 2002 07:57:20 +0200 |
parents | 1906116a62ce |
children | 0d852af6842e |
comparison
equal
deleted
inserted
replaced
613:1906116a62ce | 614:e60620644af3 |
---|---|
42 static Timeout to; | 42 static Timeout to; |
43 | 43 |
44 static HashTable *processes; | 44 static HashTable *processes; |
45 static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process; | 45 static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process; |
46 static unsigned int listening_processes; | 46 static unsigned int listening_processes; |
47 static unsigned int wanted_processes_count; | |
47 | 48 |
48 static void login_process_destroy(LoginProcess *p); | 49 static void login_process_destroy(LoginProcess *p); |
49 static void login_process_unref(LoginProcess *p); | 50 static void login_process_unref(LoginProcess *p); |
50 | 51 |
51 static void auth_callback(AuthCookieReplyData *cookie_reply, void *context) | 52 static void auth_callback(AuthCookieReplyData *cookie_reply, void *context) |
84 (void)close(request->fd); | 85 (void)close(request->fd); |
85 login_process_unref(process); | 86 login_process_unref(process); |
86 i_free(request); | 87 i_free(request); |
87 } | 88 } |
88 | 89 |
90 void login_process_mark_nonlistening(LoginProcess *p) | |
91 { | |
92 if (!p->listening) { | |
93 i_error("login: received another \"not listening\" " | |
94 "notification"); | |
95 return; | |
96 } | |
97 | |
98 p->listening = FALSE; | |
99 listening_processes--; | |
100 | |
101 p->prev_nonlisten = newest_nonlisten_process; | |
102 | |
103 if (newest_nonlisten_process != NULL) | |
104 newest_nonlisten_process->next_nonlisten = p; | |
105 newest_nonlisten_process = p; | |
106 | |
107 if (oldest_nonlisten_process == NULL) | |
108 oldest_nonlisten_process = p; | |
109 } | |
110 | |
89 static void login_process_input(void *context, int fd __attr_unused__, | 111 static void login_process_input(void *context, int fd __attr_unused__, |
90 IO io __attr_unused__) | 112 IO io __attr_unused__) |
91 { | 113 { |
92 LoginProcess *p = context; | 114 LoginProcess *p = context; |
93 AuthProcess *auth_process; | 115 AuthProcess *auth_process; |
111 } | 133 } |
112 | 134 |
113 if (client_fd == -1) { | 135 if (client_fd == -1) { |
114 /* just a notification that the login process isn't | 136 /* just a notification that the login process isn't |
115 listening for new connections anymore */ | 137 listening for new connections anymore */ |
116 if (!p->listening) { | 138 login_process_mark_nonlistening(p); |
117 i_error("login: received another \"not listening\" " | |
118 "notification"); | |
119 } else { | |
120 p->listening = FALSE; | |
121 listening_processes--; | |
122 | |
123 p->prev_nonlisten = newest_nonlisten_process; | |
124 | |
125 if (newest_nonlisten_process != NULL) | |
126 newest_nonlisten_process->next_nonlisten = p; | |
127 newest_nonlisten_process = p; | |
128 | |
129 if (oldest_nonlisten_process == NULL) | |
130 oldest_nonlisten_process = p; | |
131 } | |
132 return; | 139 return; |
133 } | 140 } |
134 | 141 |
135 /* login process isn't trusted, validate all data to make sure | 142 /* login process isn't trusted, validate all data to make sure |
136 it's not trying to exploit us */ | 143 it's not trying to exploit us */ |
340 } | 347 } |
341 | 348 |
342 static void login_processes_start_missing(void *context __attr_unused__, | 349 static void login_processes_start_missing(void *context __attr_unused__, |
343 Timeout timeout __attr_unused__) | 350 Timeout timeout __attr_unused__) |
344 { | 351 { |
345 /* create max. one process every second, that way if it keeps | 352 if (!set_login_process_per_connection) { |
346 dying all the time we don't eat all cpu with fork()ing. */ | 353 /* create max. one process every second, that way if it keeps |
347 if (listening_processes < set_login_processes_count) | 354 dying all the time we don't eat all cpu with fork()ing. */ |
348 (void)create_login_process(); | 355 if (listening_processes < set_login_processes_count) |
356 (void)create_login_process(); | |
357 } else { | |
358 /* we want to respond fast when multiple clients are connecting | |
359 at once, but we also want to prevent fork-bombing. use the | |
360 same method as apache: check once a second if we need new | |
361 processes. if yes and we've used all the existing processes, | |
362 double their amount (unless we've hit the high limit). | |
363 Then for each second that didn't use all existing processes, | |
364 drop the max. process count by one. */ | |
365 if (wanted_processes_count < set_login_processes_count) | |
366 wanted_processes_count = set_login_processes_count; | |
367 else if (listening_processes == 0) | |
368 wanted_processes_count *= 2; | |
369 else if (wanted_processes_count > set_login_processes_count) | |
370 wanted_processes_count--; | |
371 | |
372 if (wanted_processes_count > set_login_max_processes_count) | |
373 wanted_processes_count = set_login_max_processes_count; | |
374 | |
375 while (listening_processes < wanted_processes_count) | |
376 (void)create_login_process(); | |
377 } | |
349 } | 378 } |
350 | 379 |
351 void login_processes_init(void) | 380 void login_processes_init(void) |
352 { | 381 { |
353 auth_id_counter = 0; | 382 auth_id_counter = 0; |
354 listening_processes = 0; | 383 listening_processes = 0; |
384 wanted_processes_count = 0; | |
355 oldest_nonlisten_process = newest_nonlisten_process = NULL; | 385 oldest_nonlisten_process = newest_nonlisten_process = NULL; |
356 | 386 |
357 processes = hash_create(default_pool, 128, NULL, NULL); | 387 processes = hash_create(default_pool, 128, NULL, NULL); |
358 to = timeout_add(1000, login_processes_start_missing, NULL); | 388 to = timeout_add(1000, login_processes_start_missing, NULL); |
359 } | 389 } |