dovecot-2.0-sslstream: master: anvil process now stays alive acr...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 13 02:55:44 EET 2010
details: http://hg.dovecot.org/dovecot-2.0-sslstream/rev/01676e67cf38
changeset: 10201:01676e67cf38
user: Timo Sirainen <tss at iki.fi>
date: Mon Oct 26 23:45:18 2009 -0400
description:
master: anvil process now stays alive across SIGHUPs.
diffstat:
8 files changed, 211 insertions(+), 127 deletions(-)
src/master/main.c | 16 +++-
src/master/service-anvil.c | 161 +++++++++++++++++++++++-------------------
src/master/service-anvil.h | 30 ++++++-
src/master/service-listen.c | 31 ++++++--
src/master/service-monitor.c | 13 ++-
src/master/service-process.c | 52 ++++++-------
src/master/service.c | 23 ++++--
src/master/service.h | 12 +--
diffs (truncated from 604 to 300 lines):
diff -r 9d13e9f78d52 -r 01676e67cf38 src/master/main.c
--- a/src/master/main.c Mon Oct 26 23:41:54 2009 -0400
+++ b/src/master/main.c Mon Oct 26 23:45:18 2009 -0400
@@ -14,6 +14,7 @@
#include "askpass.h"
#include "capabilities.h"
#include "service.h"
+#include "service-anvil.h"
#include "service-listen.h"
#include "service-monitor.h"
#include "service-process.h"
@@ -295,6 +296,7 @@ sig_settings_reload(const siginfo_t *si
const struct master_settings *set;
void **sets;
struct service_list *new_services;
+ struct service *service;
const char *error;
i_warning("SIGHUP received - reloading configuration");
@@ -334,7 +336,17 @@ sig_settings_reload(const siginfo_t *si
/* switch to new configuration. */
services_monitor_stop(services);
- (void)services_listen_using(new_services, services);
+ if (services_listen_using(new_services, services) < 0) {
+ services_monitor_start(services);
+ return;
+ }
+
+ /* anvil never dies. it just gets moved to the new services list */
+ service = service_lookup_type(services, SERVICE_TYPE_ANVIL);
+ if (service != NULL) {
+ while (service->processes != NULL)
+ service_process_destroy(service->processes);
+ }
services_destroy(services);
services = new_services;
@@ -416,6 +428,7 @@ static void main_deinit(void)
i_free(pidfile_path);
services_destroy(services);
+ service_anvil_global_deinit();
service_pids_deinit();
}
@@ -740,6 +753,7 @@ int main(int argc, char *argv[])
/* create service structures from settings. if there are any errors in
service configuration we'll catch it here. */
service_pids_init();
+ service_anvil_global_init();
if (services_create(set, child_process_env, &services, &error) < 0)
i_fatal("%s", error);
diff -r 9d13e9f78d52 -r 01676e67cf38 src/master/service-anvil.c
--- a/src/master/service-anvil.c Mon Oct 26 23:41:54 2009 -0400
+++ b/src/master/service-anvil.c Mon Oct 26 23:45:18 2009 -0400
@@ -13,17 +13,18 @@
#define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n"
+struct service_anvil_global *service_anvil_global;
+
static void
-service_list_anvil_discard_input_stop(struct service_list *service_list)
+service_list_anvil_discard_input_stop(struct service_anvil_global *anvil)
{
- if (service_list->anvil_io_blocking != NULL) {
- io_remove(&service_list->anvil_io_blocking);
- io_remove(&service_list->anvil_io_nonblocking);
+ if (anvil->io_blocking != NULL) {
+ io_remove(&anvil->io_blocking);
+ io_remove(&anvil->io_nonblocking);
}
}
-static void
-anvil_input_fd_discard(struct service_list *service_list, int fd)
+static void anvil_input_fd_discard(struct service_anvil_global *anvil, int fd)
{
char buf[1024];
ssize_t ret;
@@ -31,30 +32,29 @@ anvil_input_fd_discard(struct service_li
ret = read(fd, buf, sizeof(buf));
if (ret <= 0) {
i_error("read(anvil fd) failed: %m");
- service_list_anvil_discard_input_stop(service_list);
+ service_list_anvil_discard_input_stop(anvil);
}
}
-static void anvil_input_blocking_discard(struct service_list *service_list)
+static void anvil_input_blocking_discard(struct service_anvil_global *anvil)
{
- anvil_input_fd_discard(service_list,
- service_list->blocking_anvil_fd[0]);
+ anvil_input_fd_discard(anvil, anvil->blocking_fd[0]);
}
-static void anvil_input_nonblocking_discard(struct service_list *service_list)
+static void anvil_input_nonblocking_discard(struct service_anvil_global *anvil)
{
- anvil_input_fd_discard(service_list,
- service_list->nonblocking_anvil_fd[0]);
+ anvil_input_fd_discard(anvil, anvil->nonblocking_fd[0]);
}
-static void service_list_anvil_discard_input(struct service_list *service_list)
+static void service_list_anvil_discard_input(struct service_anvil_global *anvil)
{
- service_list->anvil_io_blocking =
- io_add(service_list->blocking_anvil_fd[0], IO_READ,
- anvil_input_blocking_discard, service_list);
- service_list->anvil_io_nonblocking =
- io_add(service_list->nonblocking_anvil_fd[0], IO_READ,
- anvil_input_nonblocking_discard, service_list);
+ if (anvil->io_blocking != NULL)
+ return;
+
+ anvil->io_blocking = io_add(anvil->blocking_fd[0], IO_READ,
+ anvil_input_blocking_discard, anvil);
+ anvil->io_nonblocking = io_add(anvil->nonblocking_fd[0], IO_READ,
+ anvil_input_nonblocking_discard, anvil);
}
static int anvil_send_handshake(int fd, const char **error_r)
@@ -89,71 +89,90 @@ service_process_write_anvil_kill(int fd,
return 0;
}
-int service_list_init_anvil(struct service_list *service_list,
- const char **error_r)
+void service_anvil_monitor_start(struct service_list *service_list)
{
- if (pipe(service_list->blocking_anvil_fd) < 0) {
- *error_r = t_strdup_printf("pipe() failed: %m");
- return -1;
+ struct service *service;
+
+ if (service_anvil_global->process_count == 0)
+ service_list_anvil_discard_input(service_anvil_global);
+ else {
+ service = service_lookup_type(service_list, SERVICE_TYPE_ANVIL);
+ service_process_create(service);
}
- if (pipe(service_list->nonblocking_anvil_fd) < 0) {
- (void)close(service_list->blocking_anvil_fd[0]);
- (void)close(service_list->blocking_anvil_fd[1]);
- *error_r = t_strdup_printf("pipe() failed: %m");
- return -1;
- }
- fd_set_nonblock(service_list->nonblocking_anvil_fd[1], TRUE);
-
- fd_close_on_exec(service_list->blocking_anvil_fd[0], TRUE);
- fd_close_on_exec(service_list->blocking_anvil_fd[1], TRUE);
- fd_close_on_exec(service_list->nonblocking_anvil_fd[0], TRUE);
- fd_close_on_exec(service_list->nonblocking_anvil_fd[1], TRUE);
-
- i_assert(service_list->anvil_kills == NULL);
- service_list->anvil_kills =
- service_process_notify_init(service_list->nonblocking_anvil_fd[1],
- service_process_write_anvil_kill);
- return 0;
}
-void services_anvil_init(struct service_list *service_list)
+void service_anvil_process_created(struct service_process *process)
{
- /* this can't be in _init_anvil() because we can't do io_add()s
- before forking with kqueue. */
- service_list_anvil_discard_input(service_list);
+ struct service_anvil_global *anvil = service_anvil_global;
+ const char *error;
+
+ service_anvil_global->pid = process->pid;
+ service_anvil_global->uid = process->uid;
+ service_anvil_global->process_count++;
+ service_list_anvil_discard_input_stop(anvil);
+
+ if (anvil_send_handshake(anvil->blocking_fd[1], &error) < 0 ||
+ anvil_send_handshake(anvil->nonblocking_fd[1], &error) < 0)
+ service_error(process->service, "%s", error);
}
-void service_list_deinit_anvil(struct service_list *service_list)
+void service_anvil_process_destroyed(struct service_process *process)
{
- service_list_anvil_discard_input_stop(service_list);
- service_process_notify_deinit(&service_list->anvil_kills);
- if (close(service_list->blocking_anvil_fd[0]) < 0)
- i_error("close(anvil) failed: %m");
- if (close(service_list->blocking_anvil_fd[1]) < 0)
- i_error("close(anvil) failed: %m");
- if (close(service_list->nonblocking_anvil_fd[0]) < 0)
- i_error("close(anvil) failed: %m");
- if (close(service_list->nonblocking_anvil_fd[1]) < 0)
- i_error("close(anvil) failed: %m");
- service_list->blocking_anvil_fd[0] = -1;
+ i_assert(service_anvil_global->process_count > 0);
+ if (--service_anvil_global->process_count == 0)
+ service_list_anvil_discard_input(service_anvil_global);
+
+ if (service_anvil_global->pid == process->pid)
+ service_anvil_global->pid = 0;
}
-void service_anvil_process_created(struct service *service)
+void service_anvil_global_init(void)
{
- struct service_list *list = service->list;
- const char *error;
+ struct service_anvil_global *anvil;
- service_list_anvil_discard_input_stop(service->list);
+ anvil = i_new(struct service_anvil_global, 1);
+ if (pipe(anvil->status_fd) < 0)
+ i_fatal("pipe() failed: %m");
+ if (pipe(anvil->blocking_fd) < 0)
+ i_fatal("pipe() failed: %m");
+ if (pipe(anvil->nonblocking_fd) < 0)
+ i_fatal("pipe() 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);
- if (anvil_send_handshake(list->blocking_anvil_fd[1], &error) < 0 ||
- anvil_send_handshake(list->nonblocking_anvil_fd[1], &error) < 0)
- service_error(service, "%s", error);
+ fd_close_on_exec(anvil->status_fd[0], TRUE);
+ fd_close_on_exec(anvil->status_fd[1], TRUE);
+ fd_close_on_exec(anvil->blocking_fd[0], TRUE);
+ 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);
+
+ anvil->kills =
+ service_process_notify_init(anvil->nonblocking_fd[1],
+ service_process_write_anvil_kill);
+ service_anvil_global = anvil;
}
-void service_anvil_process_destroyed(struct service *service)
+void service_anvil_global_deinit(void)
{
- if (service->process_count == 0 &&
- service->list->anvil_io_blocking == NULL &&
- service->list->blocking_anvil_fd[0] != -1)
- service_list_anvil_discard_input(service->list);
+ struct service_anvil_global *anvil = service_anvil_global;
+
+ service_list_anvil_discard_input_stop(anvil);
+ service_process_notify_deinit(&anvil->kills);
+ if (close(anvil->blocking_fd[0]) < 0)
+ i_error("close(anvil) failed: %m");
+ if (close(anvil->blocking_fd[1]) < 0)
+ i_error("close(anvil) failed: %m");
+ if (close(anvil->nonblocking_fd[0]) < 0)
+ i_error("close(anvil) failed: %m");
+ if (close(anvil->nonblocking_fd[1]) < 0)
+ i_error("close(anvil) failed: %m");
+ if (close(anvil->status_fd[0]) < 0)
+ i_error("close(anvil) failed: %m");
+ if (close(anvil->status_fd[1]) < 0)
+ i_error("close(anvil) failed: %m");
+ i_free(anvil);
+
+ service_anvil_global = NULL;
}
diff -r 9d13e9f78d52 -r 01676e67cf38 src/master/service-anvil.h
--- a/src/master/service-anvil.h Mon Oct 26 23:41:54 2009 -0400
+++ b/src/master/service-anvil.h Mon Oct 26 23:45:18 2009 -0400
@@ -1,12 +1,30 @@
#ifndef SERVICE_ANVIL_H
#define SERVICE_ANVIL_H
-int service_list_init_anvil(struct service_list *service_list,
- const char **error_r);
-void service_list_deinit_anvil(struct service_list *service_list);
-void services_anvil_init(struct service_list *service_list);
+struct service_anvil_global {
+ pid_t pid;
+ unsigned int uid;
-void service_anvil_process_created(struct service *service);
-void service_anvil_process_destroyed(struct service *service);
+ int status_fd[2];
+ /* passed to child processes */
+ int blocking_fd[2];
+ /* used by master process to notify about dying processes */
+ int nonblocking_fd[2];
+
+ struct service_process_notify *kills;
+ struct io *io_blocking, *io_nonblocking;
+
+ unsigned int process_count;
+};
+
+extern struct service_anvil_global *service_anvil_global;
+
+void service_anvil_monitor_start(struct service_list *service_list);
More information about the dovecot-cvs
mailing list