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