changeset 9437:e18fb0a361ef HEAD

lib-master: Fixed crashing on deinit when listening on fifos.
author Timo Sirainen <tss@iki.fi>
date Wed, 03 Jun 2009 17:08:26 -0400
parents 4f46cee3a1d4
children 27dfd1f5d46b
files src/lib-master/master-service.c
diffstat 1 files changed, 27 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-master/master-service.c	Wed Jun 03 16:45:23 2009 -0400
+++ b/src/lib-master/master-service.c	Wed Jun 03 17:08:26 2009 -0400
@@ -403,10 +403,8 @@
 
 void master_service_client_connection_destroyed(struct master_service *service)
 {
-	if (service->listeners == NULL) {
-		/* we can listen again */
-		io_listeners_add(service);
-	}
+	/* we can listen again */
+	io_listeners_add(service);
 
 	i_assert(service->total_available_count > 0);
 
@@ -487,9 +485,14 @@
 			return;
 		}
 		/* it's not a socket. probably a fifo. use the "listener"
-		   as the connection fd */
+		   as the connection fd and stop the listener. */
 		io_remove(&l->io);
-		conn.fd = l->fd;
+		conn.fd = dup(l->fd);
+		if (conn.fd == -1) {
+			i_error("dup() failed: %m");
+			return;
+		}
+		io_remove(&l->io);
 	}
 	conn.ssl = l->ssl;
 	net_set_nonblock(conn.fd, TRUE);
@@ -500,7 +503,7 @@
         l->service->callback(&conn);
 }
 
-static void io_listeners_add(struct master_service *service)
+static void io_listeners_init(struct master_service *service)
 {
 	unsigned int i;
 
@@ -515,14 +518,29 @@
 
 		l->service = service;
 		l->fd = MASTER_LISTEN_FD_FIRST + i;
-		l->io = io_add(MASTER_LISTEN_FD_FIRST + i, IO_READ,
-			       master_service_listen, l);
 
 		if (i >= service->socket_count - service->ssl_socket_count)
 			l->ssl = TRUE;
 	}
 }
 
+static void io_listeners_add(struct master_service *service)
+{
+	unsigned int i;
+
+	if (service->listeners == NULL)
+		io_listeners_init(service);
+
+	for (i = 0; i < service->socket_count; i++) {
+		struct master_service_listener *l = &service->listeners[i];
+
+		if (l->io == NULL) {
+			l->io = io_add(MASTER_LISTEN_FD_FIRST + i, IO_READ,
+				       master_service_listen, l);
+		}
+	}
+}
+
 static void io_listeners_remove(struct master_service *service)
 {
 	unsigned int i;
@@ -532,7 +550,6 @@
 			if (service->listeners[i].io != NULL)
 				io_remove(&service->listeners[i].io);
 		}
-		i_free_and_null(service->listeners);
 	}
 }