[dovecot-cvs] dovecot/src/master login-process.c,1.8,1.9 settings.c,1.14,1.15 settings.h,1.8,1.9

cras at procontrol.fi cras at procontrol.fi
Sat Nov 16 07:57:22 EET 2002


Update of /home/cvs/dovecot/src/master
In directory danu:/tmp/cvs-serv5224/src/master

Modified Files:
	login-process.c settings.c settings.h 
Log Message:
login_process_per_connection = yes scales now better when multiple users are
trying to log in at the same time.



Index: login-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- login-process.c	16 Nov 2002 05:21:21 -0000	1.8
+++ login-process.c	16 Nov 2002 05:57:20 -0000	1.9
@@ -44,6 +44,7 @@
 static HashTable *processes;
 static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process;
 static unsigned int listening_processes;
+static unsigned int wanted_processes_count;
 
 static void login_process_destroy(LoginProcess *p);
 static void login_process_unref(LoginProcess *p);
@@ -86,6 +87,27 @@
 	i_free(request);
 }
 
+void login_process_mark_nonlistening(LoginProcess *p)
+{
+	if (!p->listening) {
+		i_error("login: received another \"not listening\" "
+			"notification");
+		return;
+	}
+
+	p->listening = FALSE;
+	listening_processes--;
+
+	p->prev_nonlisten = newest_nonlisten_process;
+
+	if (newest_nonlisten_process != NULL)
+		newest_nonlisten_process->next_nonlisten = p;
+	newest_nonlisten_process = p;
+
+	if (oldest_nonlisten_process == NULL)
+		oldest_nonlisten_process = p;
+}
+
 static void login_process_input(void *context, int fd __attr_unused__,
 				IO io __attr_unused__)
 {
@@ -113,22 +135,7 @@
 	if (client_fd == -1) {
 		/* just a notification that the login process isn't
 		   listening for new connections anymore */
-		if (!p->listening) {
-			i_error("login: received another \"not listening\" "
-				"notification");
-		} else {
-			p->listening = FALSE;
-			listening_processes--;
-
-			p->prev_nonlisten = newest_nonlisten_process;
-
-			if (newest_nonlisten_process != NULL)
-				newest_nonlisten_process->next_nonlisten = p;
-			newest_nonlisten_process = p;
-
-			if (oldest_nonlisten_process == NULL)
-                                oldest_nonlisten_process = p;
-		}
+		login_process_mark_nonlistening(p);
 		return;
 	}
 
@@ -342,16 +349,39 @@
 static void login_processes_start_missing(void *context __attr_unused__,
 					  Timeout timeout __attr_unused__)
 {
-	/* create max. one process every second, that way if it keeps
-	   dying all the time we don't eat all cpu with fork()ing. */
-	if (listening_processes < set_login_processes_count)
-                (void)create_login_process();
+	if (!set_login_process_per_connection) {
+		/* create max. one process every second, that way if it keeps
+		   dying all the time we don't eat all cpu with fork()ing. */
+		if (listening_processes < set_login_processes_count)
+			(void)create_login_process();
+	} else {
+		/* we want to respond fast when multiple clients are connecting
+		   at once, but we also want to prevent fork-bombing. use the
+		   same method as apache: check once a second if we need new
+		   processes. if yes and we've used all the existing processes,
+		   double their amount (unless we've hit the high limit).
+		   Then for each second that didn't use all existing processes,
+		   drop the max. process count by one. */
+		if (wanted_processes_count < set_login_processes_count)
+			wanted_processes_count = set_login_processes_count;
+		else if (listening_processes == 0)
+			wanted_processes_count *= 2;
+		else if (wanted_processes_count > set_login_processes_count)
+			wanted_processes_count--;
+
+		if (wanted_processes_count > set_login_max_processes_count)
+			wanted_processes_count = set_login_max_processes_count;
+
+		while (listening_processes < wanted_processes_count)
+			(void)create_login_process();
+	}
 }
 
 void login_processes_init(void)
 {
         auth_id_counter = 0;
 	listening_processes = 0;
+        wanted_processes_count = 0;
 	oldest_nonlisten_process = newest_nonlisten_process = NULL;
 
 	processes = hash_create(default_pool, 128, NULL, NULL);

Index: settings.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/settings.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- settings.c	16 Nov 2002 05:21:21 -0000	1.14
+++ settings.c	16 Nov 2002 05:57:20 -0000	1.15
@@ -92,6 +92,7 @@
 int set_login_chroot = TRUE;
 int set_login_process_per_connection = TRUE;
 unsigned int set_login_processes_count = 3;
+unsigned int set_login_max_processes_count = 128;
 unsigned int set_max_logging_users = 256;
 
 uid_t set_login_uid; /* generated from set_login_user */

Index: settings.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/settings.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- settings.h	16 Nov 2002 05:21:21 -0000	1.8
+++ settings.h	16 Nov 2002 05:57:20 -0000	1.9
@@ -21,7 +21,7 @@
 extern char *set_login_dir;
 extern int set_login_chroot;
 extern int set_login_process_per_connection;
-extern unsigned int set_login_processes_count;
+extern unsigned int set_login_processes_count, set_login_max_processes_count;
 extern unsigned int set_max_logging_users;
 
 extern uid_t set_login_uid;




More information about the dovecot-cvs mailing list