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 }