dovecot: Support listening multiple sockets. SIGHUP also doesn't...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jul 3 20:04:32 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/3f2eb1b9c555
changeset: 5887:3f2eb1b9c555
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jul 03 20:04:28 2007 +0300
description:
Support listening multiple sockets. SIGHUP also doesn't anymore recreate
listener sockets.

diffstat:

12 files changed, 601 insertions(+), 333 deletions(-)
dovecot-example.conf                |    8 
src/login-common/main.c             |  123 +++++++----
src/master/Makefile.am              |    4 
src/master/dup2-array.c             |   80 +++++++
src/master/dup2-array.h             |   13 +
src/master/listener.c               |  366 +++++++++++++++++++++++++++++++++++
src/master/listener.h               |    7 
src/master/login-process.c          |   59 +++--
src/master/main.c                   |  256 ------------------------
src/master/master-login-interface.h |    2 
src/master/master-settings.c        |    2 
src/master/master-settings.h        |   14 -

diffs (truncated from 1193 to 300 lines):

diff -r 86f22b84e008 -r 3f2eb1b9c555 dovecot-example.conf
--- a/dovecot-example.conf	Tue Jul 03 18:34:31 2007 +0300
+++ b/dovecot-example.conf	Tue Jul 03 20:04:28 2007 +0300
@@ -22,10 +22,10 @@
 # If you only want to use dovecot-auth, you can set this to "none".
 #protocols = imap imaps
 
-# IP or host address where to listen in for connections. It's not currently
-# possible to specify multiple addresses. "*" listens in all IPv4 interfaces.
-# "[::]" listens in all IPv6 interfaces, but may also listen in all IPv4
-# interfaces depending on the operating system.
+# A space separated list of IP or host addresses where to listen in for
+# connections. "*" listens in all IPv4 interfaces. "[::]" listens in all IPv6
+# interfaces, but may also listen in all IPv4 interfaces depending on the
+# operating system.
 #
 # If you want to specify ports for each service, you will need to configure
 # these settings inside the protocol imap/pop3 { ... } section, so you can
diff -r 86f22b84e008 -r 3f2eb1b9c555 src/login-common/main.c
--- a/src/login-common/main.c	Tue Jul 03 18:34:31 2007 +0300
+++ b/src/login-common/main.c	Tue Jul 03 20:04:28 2007 +0300
@@ -2,6 +2,7 @@
 
 #include "common.h"
 #include "ioloop.h"
+#include "array.h"
 #include "lib-signals.h"
 #include "randgen.h"
 #include "restrict-access.h"
@@ -29,9 +30,11 @@ bool closing_down;
 
 static const char *process_name;
 static struct ioloop *ioloop;
-static struct io *io_listen, *io_ssl_listen;
 static int main_refcount;
 static bool is_inetd, listening;
+
+static ARRAY_DEFINE(listen_ios, struct io *);
+static unsigned int listen_count, ssl_listen_count;
 
 void main_ref(void)
 {
@@ -71,14 +74,15 @@ static void sig_die(int signo, void *con
 	io_loop_stop(ioloop);
 }
 
-static void login_accept(void *context __attr_unused__)
-{
+static void login_accept(void *context)
+{
+	int listen_fd = POINTER_CAST_TO(context, int);
 	struct ip_addr remote_ip, local_ip;
 	unsigned int remote_port, local_port;
 	struct client *client;
 	int fd;
 
-	fd = net_accept(LOGIN_LISTEN_FD, &remote_ip, &remote_port);
+	fd = net_accept(listen_fd, &remote_ip, &remote_port);
 	if (fd < 0) {
 		if (fd < -1)
 			i_error("accept() failed: %m");
@@ -100,15 +104,16 @@ static void login_accept(void *context _
 	}
 }
 
-static void login_accept_ssl(void *context __attr_unused__)
-{
+static void login_accept_ssl(void *context)
+{
+	int listen_fd = POINTER_CAST_TO(context, int);
 	struct ip_addr remote_ip, local_ip;
 	unsigned int remote_port, local_port;
 	struct client *client;
 	struct ssl_proxy *proxy;
 	int fd, fd_ssl;
 
-	fd = net_accept(LOGIN_SSL_LISTEN_FD, &remote_ip, &remote_port);
+	fd = net_accept(listen_fd, &remote_ip, &remote_port);
 	if (fd < 0) {
 		if (fd < -1)
 			i_error("accept() failed: %m");
@@ -138,7 +143,9 @@ static void login_accept_ssl(void *conte
 
 void main_listen_start(void)
 {
-	unsigned int current_count;
+	struct io *io;
+	unsigned int i, current_count;
+	int cur_fd;
 
 	if (listening)
 		return;
@@ -156,21 +163,17 @@ void main_listen_start(void)
 		return;
 	}
 
-	if (net_getsockname(LOGIN_LISTEN_FD, NULL, NULL) == 0) {
-		io_listen = io_add(LOGIN_LISTEN_FD, IO_READ,
-				   login_accept, NULL);
-	}
-
-	if (net_getsockname(LOGIN_SSL_LISTEN_FD, NULL, NULL) == 0) {
-		if (!ssl_initialized) {
-			/* this shouldn't happen, master should have
-			   disabled the ssl socket.. */
-			i_fatal("BUG: SSL initialization parameters not given "
-				"while they should have been");
-		}
-
-		io_ssl_listen = io_add(LOGIN_SSL_LISTEN_FD, IO_READ,
-				       login_accept_ssl, NULL);
+	cur_fd = LOGIN_MASTER_SOCKET_FD + 1;
+	i_array_init(&listen_ios, listen_count + ssl_listen_count);
+	for (i = 0; i < listen_count; i++, cur_fd++) {
+		io = io_add(cur_fd, IO_READ, login_accept,
+			    POINTER_CAST(cur_fd));
+		array_append(&listen_ios, &io, 1);
+	}
+	for (i = 0; i < ssl_listen_count; i++, cur_fd++) {
+		io = io_add(cur_fd, IO_READ, login_accept_ssl,
+			    POINTER_CAST(cur_fd));
+		array_append(&listen_ios, &io, 1);
 	}
 	listening = TRUE;
 
@@ -181,30 +184,34 @@ void main_listen_start(void)
 
 void main_listen_stop(void)
 {
+	struct io **ios;
+	unsigned int i, count;
+	int cur_fd;
+
 	if (!listening)
 		return;
 
+	ios = array_get_modifiable(&listen_ios, &count);
+	for (i = 0; i < count; i++)
+		io_remove(&ios[i]);
+	array_free(&listen_ios);
+
+	if (closing_down) {
+		cur_fd = LOGIN_MASTER_SOCKET_FD + 1;
+		for (i = 0; i < count; i++, cur_fd++) {
+			if (close(cur_fd) < 0) {
+				i_fatal("close(listener %d) failed: %m",
+					cur_fd);
+			}
+		}
+	}
+
 	listening = FALSE;
-	if (io_listen != NULL) {
-		io_remove(&io_listen);
-		if (closing_down) {
-			if (close(LOGIN_LISTEN_FD) < 0)
-				i_fatal("close(listen) failed: %m");
-		}
-	}
-
-	if (io_ssl_listen != NULL) {
-		io_remove(&io_ssl_listen);
-		if (closing_down) {
-			if (close(LOGIN_SSL_LISTEN_FD) < 0)
-				i_fatal("close(ssl_listen) failed: %m");
-		}
-	}
-
-	listening = FALSE;
-	master_notify_state_change(clients_get_count() == 0 ?
-				   LOGIN_STATE_FULL_LOGINS :
-				   LOGIN_STATE_FULL_PRELOGINS);
+	if (io_loop_is_running(ioloop)) {
+		master_notify_state_change(clients_get_count() == 0 ?
+					   LOGIN_STATE_FULL_LOGINS :
+					   LOGIN_STATE_FULL_PRELOGINS);
+	}
 }
 
 void connection_queue_add(unsigned int connection_count)
@@ -332,7 +339,18 @@ static void main_init(void)
         auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
 	clients_init();
 
-	io_listen = io_ssl_listen = NULL;
+	value = getenv("LISTEN_FDS");
+	listen_count = value == NULL ? 0 : atoi(value);
+
+	value = getenv("SSL_LISTEN_FDS");
+	ssl_listen_count = value == NULL ? 0 : atoi(value);
+
+	if (!ssl_initialized && ssl_listen_count > 0) {
+		/* this shouldn't happen, master should have
+		   disabled the ssl socket.. */
+		i_fatal("BUG: SSL initialization parameters not given "
+			"while they should have been");
+	}
 
 	if (!is_inetd) {
 		master_init(LOGIN_MASTER_SOCKET_FD);
@@ -342,8 +360,8 @@ static void main_init(void)
 
 static void main_deinit(void)
 {
-	if (io_listen != NULL) io_remove(&io_listen);
-	if (io_ssl_listen != NULL) io_remove(&io_ssl_listen);
+	closing_down = TRUE;
+	main_listen_stop();
 
 	ssl_proxy_deinit();
 	login_proxy_deinit();
@@ -370,8 +388,17 @@ int main(int argc __attr_unused__, char 
 	is_inetd = getenv("DOVECOT_MASTER") == NULL;
 
 #ifdef DEBUG
-	if (!is_inetd && getenv("GDB") == NULL)
-		fd_debug_verify_leaks(5, 1024);
+	if (!is_inetd && getenv("GDB") == NULL) {
+		const char *env;
+
+		i = LOGIN_MASTER_SOCKET_FD + 1;
+		env = getenv("LISTEN_FDS");
+		if (env != NULL) i += atoi(env);
+		env = getenv("SSL_LISTEN_FDS");
+		if (env != NULL) i += atoi(env);
+
+		fd_debug_verify_leaks(i + 1, 1024);
+	}
 #endif
 	/* clear all allocated memory before freeing it. this makes the login
 	   processes pretty safe to reuse for new connections since the
diff -r 86f22b84e008 -r 3f2eb1b9c555 src/master/Makefile.am
--- a/src/master/Makefile.am	Tue Jul 03 18:34:31 2007 +0300
+++ b/src/master/Makefile.am	Tue Jul 03 20:04:28 2007 +0300
@@ -24,6 +24,8 @@ dovecot_SOURCES = \
 	capabilities-posix.c \
 	child-process.c \
 	dict-process.c \
+	dup2-array.c \
+	listener.c \
 	log.c \
 	login-process.c \
 	mail-process.c \
@@ -38,6 +40,8 @@ noinst_HEADERS = \
 	capabilities.h \
 	child-process.h \
 	dict-process.h \
+	dup2-array.h \
+	listener.h \
 	common.h \
 	log.h \
 	login-process.h \
diff -r 86f22b84e008 -r 3f2eb1b9c555 src/master/dup2-array.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/master/dup2-array.c	Tue Jul 03 20:04:28 2007 +0300
@@ -0,0 +1,80 @@
+/* Copyright (C) 2007 Timo Sirainen */
+
+#include "lib.h"
+#include "array.h"
+#include "fd-close-on-exec.h"
+#include "dup2-array.h"
+
+#include <unistd.h>
+
+void dup2_append(ARRAY_TYPE(dup2) *dups, int fd_src, int fd_dest)
+{
+	struct dup2 d;
+
+	d.fd_src = fd_src;
+	d.fd_dest = fd_dest;
+	array_append(dups, &d, 1);
+}
+
+int dup2_array(ARRAY_TYPE(dup2) *dups_arr)
+{
+	struct dup2 *dups;
+	bool *moved, moves;
+	unsigned int i, j, count, conflict;
+	int fd;
+
+	dups = array_get_modifiable(dups_arr, &count);
+
+	t_push();
+	moved = t_new(bool, count);
+	for (;;) {
+		conflict = count;
+		moves = FALSE;
+		for (i = 0; i < count; i++) {
+			if (moved[i])
+				continue;
+
+			for (j = 0; j < count; j++) {
+				if (dups[j].fd_src == dups[i].fd_dest &&
+				    !moved[j]) {
+					conflict = j;
+					break;
+				}
+			}
+


More information about the dovecot-cvs mailing list