dovecot-2.0: anvil: After master gets a SIGHUP, start logging vi...

dovecot at dovecot.org dovecot at dovecot.org
Fri Dec 11 21:35:00 EET 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/802b9ebe79e6
changeset: 10454:802b9ebe79e6
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Dec 11 14:33:58 2009 -0500
description:
anvil: After master gets a SIGHUP, start logging via new log process.

diffstat:

8 files changed, 83 insertions(+), 11 deletions(-)
src/anvil/main.c                  |   30 ++++++++++++++++++++++++++++++
src/lib-master/master-interface.h |    2 ++
src/master/service-anvil.c        |   25 +++++++++++++++++++++++++
src/master/service-anvil.h        |    4 ++++
src/master/service-log.c          |   23 ++++++++++++-----------
src/master/service-process.c      |    2 ++
src/master/service.c              |    7 +++++++
src/master/service.h              |    1 +

diffs (266 lines):

diff -r 32ad99f146d1 -r 802b9ebe79e6 src/anvil/main.c
--- a/src/anvil/main.c	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/anvil/main.c	Fri Dec 11 14:33:58 2009 -0500
@@ -3,6 +3,8 @@
 #include "common.h"
 #include "array.h"
 #include "env-util.h"
+#include "fdpass.h"
+#include "ioloop.h"
 #include "restrict-access.h"
 #include "master-service.h"
 #include "master-interface.h"
@@ -10,14 +12,38 @@
 #include "penalty.h"
 #include "anvil-connection.h"
 
+#include <unistd.h>
+
 struct connect_limit *connect_limit;
 struct penalty *penalty;
+static struct io *log_fdpass_io;
 
 static void client_connected(const struct master_service_connection *conn)
 {
 	bool master = conn->listen_fd == MASTER_LISTEN_FD_FIRST;
 
 	anvil_connection_create(conn->fd, master, conn->fifo);
+}
+
+static void log_fdpass_input(void *context ATTR_UNUSED)
+{
+	int fd;
+	char c;
+	ssize_t ret;
+
+	/* master wants us to replace the log fd */
+	ret = fd_read(MASTER_ANVIL_LOG_FDPASS_FD, &c, 1, &fd);
+	if (ret < 0)
+		i_error("fd_read(log fd) failed: %m");
+	else if (ret == 0) {
+		/* master died. lib-master should notice it soon. */
+		io_remove(&log_fdpass_io);
+	} else {
+		if (dup2(fd, STDERR_FILENO) < 0)
+			i_fatal("dup2(fd_read  log fd, stderr) failed: %m");
+		if (close(fd) < 0)
+			i_error("close(fd_read log fd) failed: %m");
+	}
 }
 
 int main(int argc, char *argv[])
@@ -33,9 +59,13 @@ int main(int argc, char *argv[])
 	master_service_init_finish(master_service);
 	connect_limit = connect_limit_init();
 	penalty = penalty_init();
+	log_fdpass_io = io_add(MASTER_ANVIL_LOG_FDPASS_FD, IO_READ,
+			       log_fdpass_input, NULL);
 
 	master_service_run(master_service, client_connected);
 
+	if (log_fdpass_io != NULL)
+		io_remove(&log_fdpass_io);
 	penalty_deinit(&penalty);
 	connect_limit_deinit(&connect_limit);
 	anvil_connections_destroy_all();
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/lib-master/master-interface.h
--- a/src/lib-master/master-interface.h	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/lib-master/master-interface.h	Fri Dec 11 14:33:58 2009 -0500
@@ -56,6 +56,8 @@ enum master_login_state {
 
 /* Write pipe to anvil. */
 #define MASTER_ANVIL_FD 3
+/* Anvil reads new log fds from this fd */
+#define MASTER_ANVIL_LOG_FDPASS_FD 4
 /* Master's "all processes full" notification fd for login processes */
 #define MASTER_LOGIN_NOTIFY_FD 4
 
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service-anvil.c
--- a/src/master/service-anvil.c	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service-anvil.c	Fri Dec 11 14:33:58 2009 -0500
@@ -4,6 +4,7 @@
 #include "ioloop.h"
 #include "fd-close-on-exec.h"
 #include "fd-set-nonblock.h"
+#include "fdpass.h"
 #include "service.h"
 #include "service-process.h"
 #include "service-process-notify.h"
@@ -126,6 +127,22 @@ void service_anvil_process_destroyed(str
 		service_anvil_global->pid = 0;
 }
 
+void service_anvil_send_log_fd(void)
+{
+	ssize_t ret;
+	char b;
+
+	if (service_anvil_global->process_count == 0)
+		return;
+
+	ret = fd_send(service_anvil_global->log_fdpass_fd[1],
+		      services->anvil->log_fd[1], &b, 1);
+	if (ret < 0)
+		i_error("fd_send(anvil log fd) failed: %m");
+	else if (ret == 0)
+		i_error("fd_send(anvil log fd) failed: disconnected");
+}
+
 void service_anvil_global_init(void)
 {
 	struct service_anvil_global *anvil;
@@ -137,6 +154,8 @@ void service_anvil_global_init(void)
 		i_fatal("pipe() failed: %m");
 	if (pipe(anvil->nonblocking_fd) < 0)
 		i_fatal("pipe() failed: %m");
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, anvil->log_fdpass_fd) < 0)
+		i_fatal("socketpair() failed: %m");
 	fd_set_nonblock(anvil->status_fd[0], TRUE);
 	fd_set_nonblock(anvil->status_fd[1], TRUE);
 	fd_set_nonblock(anvil->nonblocking_fd[1], TRUE);
@@ -147,6 +166,8 @@ void service_anvil_global_init(void)
 	fd_close_on_exec(anvil->blocking_fd[1], TRUE);
 	fd_close_on_exec(anvil->nonblocking_fd[0], TRUE);
 	fd_close_on_exec(anvil->nonblocking_fd[1], TRUE);
+	fd_close_on_exec(anvil->log_fdpass_fd[0], TRUE);
+	fd_close_on_exec(anvil->log_fdpass_fd[1], TRUE);
 
 	anvil->kills =
 		service_process_notify_init(anvil->nonblocking_fd[1],
@@ -160,6 +181,10 @@ void service_anvil_global_deinit(void)
 
 	service_list_anvil_discard_input_stop(anvil);
 	service_process_notify_deinit(&anvil->kills);
+	if (close(anvil->log_fdpass_fd[0]) < 0)
+		i_error("close(anvil) failed: %m");
+	if (close(anvil->log_fdpass_fd[1]) < 0)
+		i_error("close(anvil) failed: %m");
 	if (close(anvil->blocking_fd[0]) < 0)
 		i_error("close(anvil) failed: %m");
 	if (close(anvil->blocking_fd[1]) < 0)
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service-anvil.h
--- a/src/master/service-anvil.h	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service-anvil.h	Fri Dec 11 14:33:58 2009 -0500
@@ -10,6 +10,8 @@ struct service_anvil_global {
 	int blocking_fd[2];
 	/* used by master process to notify about dying processes */
 	int nonblocking_fd[2];
+	/* master process sends new log fds to anvil via this unix socket */
+	int log_fdpass_fd[2];
 
 	struct service_process_notify *kills;
 	struct io *io_blocking, *io_nonblocking;
@@ -24,6 +26,8 @@ void service_anvil_process_created(struc
 void service_anvil_process_created(struct service_process *process);
 void service_anvil_process_destroyed(struct service_process *process);
 
+void service_anvil_send_log_fd(void);
+
 void service_anvil_global_init(void);
 void service_anvil_global_deinit(void);
 
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service-log.c
--- a/src/master/service-log.c	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service-log.c	Fri Dec 11 14:33:58 2009 -0500
@@ -10,6 +10,7 @@
 #include "service.h"
 #include "service-process.h"
 #include "service-process-notify.h"
+#include "service-anvil.h"
 #include "service-log.h"
 
 #include <unistd.h>
@@ -68,14 +69,12 @@ int services_log_init(struct service_lis
 int services_log_init(struct service_list *service_list)
 {
 	struct service *const *services;
-	unsigned int i, count, n;
 	const char *log_prefix;
 	buffer_t *handshake_buf;
 	ssize_t ret = 0;
+	int fd;
 
 	handshake_buf = buffer_create_dynamic(default_pool, 256);
-	services = array_get(&service_list->services, &count);
-
 	if (service_log_fds_init(MASTER_LOG_PREFIX_NAME,
 				 service_list->master_log_fd,
 				 handshake_buf) < 0)
@@ -88,20 +87,20 @@ int services_log_init(struct service_lis
 		service_process_notify_init(service_list->master_log_fd[1],
 					    service_process_write_log_bye);
 
-	n = 1;
-	for (i = 0; i < count; i++) {
-		if (services[i]->type == SERVICE_TYPE_LOG)
+	fd = MASTER_LISTEN_FD_FIRST + 1;
+	array_foreach(&service_list->services, services) {
+		struct service *service = *services;
+
+		if (service->type == SERVICE_TYPE_LOG)
 			continue;
 
-		log_prefix = t_strconcat(services[i]->set->name, ": ", NULL);
-		if (service_log_fds_init(log_prefix,
-					 services[i]->log_fd,
+		log_prefix = t_strconcat(service->set->name, ": ", NULL);
+		if (service_log_fds_init(log_prefix, service->log_fd,
 					 handshake_buf) < 0) {
 			ret = -1;
 			break;
 		}
-		services[i]->log_process_internal_fd =
-			MASTER_LISTEN_FD_FIRST + n++;
+		service->log_process_internal_fd = fd++;
 	}
 
 	buffer_free(&handshake_buf);
@@ -109,6 +108,8 @@ int services_log_init(struct service_lis
 		services_log_deinit(service_list);
 		return -1;
 	}
+
+	service_anvil_send_log_fd();
 	return 0;
 }
 
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service-process.c
--- a/src/master/service-process.c	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service-process.c	Fri Dec 11 14:33:58 2009 -0500
@@ -61,6 +61,8 @@ service_dup_fds(struct service *service)
 		n += socket_listener_count;
 		break;
 	case SERVICE_TYPE_ANVIL:
+		dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
+			    MASTER_ANVIL_LOG_FDPASS_FD);
 		/* nonblocking anvil fd must be the first one. anvil treats it
 		   as the master's fd */
 		dup2_append(&dups, service_anvil_global->nonblocking_fd[0],
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service.c
--- a/src/master/service.c	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service.c	Fri Dec 11 14:33:58 2009 -0500
@@ -409,6 +409,13 @@ int services_create(const struct master_
 			}
 			service_list->config = service;
 			break;
+		case SERVICE_TYPE_ANVIL:
+			if (service_list->anvil != NULL) {
+				*error_r = "Multiple anvil services specified";
+				return -1;
+			}
+			service_list->anvil = service;
+			break;
 		default:
 			break;
 		}
diff -r 32ad99f146d1 -r 802b9ebe79e6 src/master/service.h
--- a/src/master/service.h	Fri Dec 11 12:50:04 2009 -0500
+++ b/src/master/service.h	Fri Dec 11 14:33:58 2009 -0500
@@ -110,6 +110,7 @@ struct service_list {
 
 	struct service *config;
 	struct service *log;
+	struct service *anvil;
 	const char *const *child_process_env;
 
 	/* nonblocking log fds usd by master */


More information about the dovecot-cvs mailing list