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

cras at procontrol.fi cras at procontrol.fi
Sat Nov 16 07:21:23 EET 2002


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

Modified Files:
	login-process.c settings.c settings.h 
Log Message:
Finally support for handling each login connection in it's own process.
Enabled by default. Also a few bugfixes to master process.



Index: login-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- login-process.c	6 Nov 2002 14:20:50 -0000	1.7
+++ login-process.c	16 Nov 2002 05:21:21 -0000	1.8
@@ -14,15 +14,19 @@
 #include <unistd.h>
 #include <syslog.h>
 
-typedef struct {
+typedef struct _LoginProcess LoginProcess;
+
+struct _LoginProcess {
+	LoginProcess *prev_nonlisten, *next_nonlisten;
 	int refcount;
 
 	pid_t pid;
 	int fd;
 	IO io;
 	OBuffer *outbuf;
+	unsigned int listening:1;
 	unsigned int destroyed:1;
-} LoginProcess;
+};
 
 typedef struct {
 	LoginProcess *process;
@@ -36,7 +40,10 @@
 
 static int auth_id_counter;
 static Timeout to;
-static HashTable *processes = NULL;
+
+static HashTable *processes;
+static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process;
+static unsigned int listening_processes;
 
 static void login_process_destroy(LoginProcess *p);
 static void login_process_unref(LoginProcess *p);
@@ -103,6 +110,28 @@
 		return;
 	}
 
+	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;
+		}
+		return;
+	}
+
 	/* login process isn't trusted, validate all data to make sure
 	   it's not trying to exploit us */
 	if (!VALIDATE_STR(req.login_tag)) {
@@ -125,7 +154,7 @@
 	if (auth_process == NULL) {
 		i_error("login: Authentication process %u doesn't exist",
 			req.auth_process);
-		auth_callback(NULL, &authreq);
+		auth_callback(NULL, authreq);
 	} else {
 		auth_process_request(auth_process, authreq->auth_id, req.cookie,
 				     auth_callback, authreq);
@@ -142,26 +171,50 @@
 	p->refcount = 1;
 	p->pid = pid;
 	p->fd = fd;
+	p->listening = TRUE;
 	p->io = io_add(fd, IO_READ, login_process_input, p);
 	p->outbuf = o_buffer_create_file(fd, default_pool,
 					 sizeof(MasterReply)*10,
 					 IO_PRIORITY_DEFAULT, FALSE);
 
 	hash_insert(processes, POINTER_CAST(pid), p);
+        listening_processes++;
 	return p;
 }
 
+void login_process_remove_from_lists(LoginProcess *p)
+{
+	if (p == oldest_nonlisten_process)
+		oldest_nonlisten_process = p->next_nonlisten;
+	else
+		p->prev_nonlisten->next_nonlisten = p->next_nonlisten;
+
+	if (p == newest_nonlisten_process)
+		newest_nonlisten_process = p->prev_nonlisten;
+	else
+		p->next_nonlisten->prev_nonlisten = p->prev_nonlisten;
+
+	p->next_nonlisten = p->prev_nonlisten = NULL;
+}
+
 static void login_process_destroy(LoginProcess *p)
 {
 	if (p->destroyed)
 		return;
 	p->destroyed = TRUE;
 
+	if (p->listening)
+		listening_processes--;
+
 	o_buffer_close(p->outbuf);
 	io_remove(p->io);
 	(void)close(p->fd);
 
+	if (!p->listening)
+		login_process_remove_from_lists(p);
+
 	hash_remove(processes, POINTER_CAST(p->pid));
+
 	login_process_unref(p);
 }
 
@@ -180,6 +233,12 @@
 	pid_t pid;
 	int fd[2];
 
+	if (set_login_process_per_connection &&
+	    hash_size(processes)-listening_processes >= set_max_logging_users) {
+		if (oldest_nonlisten_process != NULL)
+			login_process_destroy(oldest_nonlisten_process);
+	}
+
 	if (set_login_uid == 0)
 		i_fatal("Login process must not run as root");
 
@@ -249,8 +308,13 @@
 	if (set_disable_plaintext_auth)
 		putenv("DISABLE_PLAINTEXT_AUTH=1");
 
-	putenv((char *) t_strdup_printf("MAX_LOGGING_USERS=%d",
-					set_max_logging_users));
+	if (set_login_process_per_connection) {
+		putenv("PROCESS_PER_CONNECTION=1");
+		putenv("MAX_LOGGING_USERS=1");
+	} else {
+		putenv((char *) t_strdup_printf("MAX_LOGGING_USERS=%d",
+						set_max_logging_users));
+	}
 
 	/* hide the path, it's ugly */
 	argv[0] = strrchr(set_login_executable, '/');
@@ -280,14 +344,17 @@
 {
 	/* 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 (hash_size(processes) < set_login_processes_count)
+	if (listening_processes < set_login_processes_count)
                 (void)create_login_process();
 }
 
 void login_processes_init(void)
 {
         auth_id_counter = 0;
-        processes = hash_create(default_pool, 128, NULL, NULL);
+	listening_processes = 0;
+	oldest_nonlisten_process = newest_nonlisten_process = NULL;
+
+	processes = hash_create(default_pool, 128, NULL, NULL);
 	to = timeout_add(1000, login_processes_start_missing, NULL);
 }
 

Index: settings.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/settings.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- settings.c	12 Nov 2002 05:27:30 -0000	1.13
+++ settings.c	16 Nov 2002 05:21:21 -0000	1.14
@@ -39,6 +39,8 @@
 	{ "login_user",		SET_STR, &set_login_user },
 	{ "login_dir",		SET_STR, &set_login_dir },
 	{ "login_chroot",	SET_BOOL,&set_login_chroot },
+	{ "login_process_per_connection",
+				SET_BOOL,&set_login_process_per_connection },
 	{ "login_processes_count",
 				SET_INT, &set_login_processes_count },
 	{ "max_logging_users",	SET_INT, &set_max_logging_users },
@@ -88,7 +90,8 @@
 char *set_login_dir = PKG_RUNDIR;
 
 int set_login_chroot = TRUE;
-unsigned int set_login_processes_count = 1;
+int set_login_process_per_connection = TRUE;
+unsigned int set_login_processes_count = 3;
 unsigned int set_max_logging_users = 256;
 
 uid_t set_login_uid; /* generated from set_login_user */
@@ -176,11 +179,18 @@
 	if (access(set_login_dir, X_OK) < 0)
 		i_fatal("Can't access login directory %s: %m", set_login_dir);
 
+	if (set_max_imap_processes < 1)
+		i_fatal("max_imap_processes must be at least 1");
 	if (set_login_processes_count < 1)
 		i_fatal("login_processes_count must be at least 1");
-	if (set_first_valid_uid < set_last_valid_uid)
+	if (set_max_logging_users < 1)
+		i_fatal("max_logging_users must be at least 1");
+
+	if (set_last_valid_uid != 0 &&
+	    set_first_valid_uid > set_last_valid_uid)
 		i_fatal("first_valid_uid can't be larger than last_valid_uid");
-	if (set_first_valid_gid < set_last_valid_gid)
+	if (set_last_valid_gid != 0 &&
+	    set_first_valid_gid > set_last_valid_gid)
 		i_fatal("first_valid_gid can't be larger than last_valid_gid");
 
 	auth_settings_verify();

Index: settings.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/settings.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- settings.h	12 Nov 2002 05:27:30 -0000	1.7
+++ settings.h	16 Nov 2002 05:21:21 -0000	1.8
@@ -20,6 +20,7 @@
 extern char *set_login_user;
 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_max_logging_users;
 




More information about the dovecot-cvs mailing list