dovecot-2.0: master: Several fixes to handling SIGHUPs.
dovecot at dovecot.org
dovecot at dovecot.org
Sat Sep 5 00:07:06 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/31a283729295
changeset: 9876:31a283729295
user: Timo Sirainen <tss at iki.fi>
date: Fri Sep 04 17:06:58 2009 -0400
description:
master: Several fixes to handling SIGHUPs.
diffstat:
7 files changed, 74 insertions(+), 26 deletions(-)
src/master/common.h | 1 +
src/master/main.c | 2 +-
src/master/service-auth-server.c | 24 ++++++++++++++++++++----
src/master/service-listen.c | 27 +++++++++++++++++----------
src/master/service-monitor.c | 16 ++++++++++------
src/master/service.c | 24 +++++++++++++++++++-----
src/master/service.h | 6 ++++++
diffs (227 lines):
diff -r 199857627883 -r 31a283729295 src/master/common.h
--- a/src/master/common.h Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/common.h Fri Sep 04 17:06:58 2009 -0400
@@ -12,6 +12,7 @@ extern bool auth_success_written;
extern bool auth_success_written;
extern bool core_dumps_disabled;
extern int null_fd;
+extern struct service_list *services;
void process_exec(const char *cmd, const char *extra_args[]) ATTR_NORETURN;
diff -r 199857627883 -r 31a283729295 src/master/main.c
--- a/src/master/main.c Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/main.c Fri Sep 04 17:06:58 2009 -0400
@@ -38,9 +38,9 @@ bool auth_success_written;
bool auth_success_written;
bool core_dumps_disabled;
int null_fd;
+struct service_list *services;
static char *pidfile_path;
-static struct service_list *services;
static fatal_failure_callback_t *orig_fatal_callback;
static const char *child_process_env[3]; /* @UNSAFE */
diff -r 199857627883 -r 31a283729295 src/master/service-auth-server.c
--- a/src/master/service-auth-server.c Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/service-auth-server.c Fri Sep 04 17:06:58 2009 -0400
@@ -83,6 +83,22 @@ auth_process_lookup_request(struct servi
return request;
}
+static struct service *
+auth_process_get_dest_service(struct service_process_auth_source *process)
+{
+ struct service *service = process->process.service;
+
+ if (!service->list->destroyed)
+ return service->auth_dest_service;
+
+ service = service_lookup(services, service->set->auth_dest_service);
+ if (service == NULL) {
+ i_warning("service(%s): Lost destination service %s",
+ service->set->name, service->set->auth_dest_service);
+ }
+ return service;
+}
+
static int
auth_process_input_user(struct service_process_auth_server *process, const char *args)
{
@@ -103,12 +119,12 @@ auth_process_input_user(struct service_p
request = auth_process_lookup_request(process, id);
if (request != NULL) {
- struct service *dest_service =
- request->process->process.service->auth_dest_service;
+ struct service *dest_service;
struct service_process *dest_process;
- dest_process = service_process_create(dest_service, list + 1,
- request);
+ dest_service = auth_process_get_dest_service(request->process);
+ dest_process = dest_service == NULL ? NULL :
+ service_process_create(dest_service, list + 1, request);
status = dest_process != NULL ?
MASTER_AUTH_STATUS_OK :
MASTER_AUTH_STATUS_INTERNAL_ERROR;
diff -r 199857627883 -r 31a283729295 src/master/service-listen.c
--- a/src/master/service-listen.c Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/service-listen.c Fri Sep 04 17:06:58 2009 -0400
@@ -190,16 +190,11 @@ static int listener_equals(const struct
switch (l1->type) {
case SERVICE_LISTENER_UNIX:
case SERVICE_LISTENER_FIFO:
- if (strcmp(l1->set.fileset.set->path,
- l2->set.fileset.set->path) != 0)
- return FALSE;
- if (l1->set.fileset.set->mode != l2->set.fileset.set->mode)
- return FALSE;
- if (l1->set.fileset.uid != l2->set.fileset.uid)
- return FALSE;
- if (l1->set.fileset.gid != l2->set.fileset.gid)
- return FALSE;
- return TRUE;
+ /* We could just keep using the same listener, but it's more
+ likely to cause problems if old process accepts a connection
+ before it knows that it should die. So just always unlink
+ and recreate unix/fifo listeners. */
+ return FALSE;
case SERVICE_LISTENER_INET:
if (memcmp(&l1->set.inetset.ip, &l2->set.inetset.ip,
sizeof(l1->set.inetset.ip)) != 0)
@@ -253,6 +248,18 @@ int services_listen_using(struct service
if (close(old_listeners[j]->fd) < 0)
i_error("close(listener) failed: %m");
}
+ switch (old_listeners[j]->type) {
+ case SERVICE_LISTENER_UNIX:
+ case SERVICE_LISTENER_FIFO: {
+ const char *path =
+ old_listeners[j]->set.fileset.set->path;
+ if (unlink(path) < 0)
+ i_error("unlink(%s) failed: %m", path);
+ break;
+ }
+ case SERVICE_LISTENER_INET:
+ break;
+ }
}
/* and let services_listen() deal with the remaining fds */
diff -r 199857627883 -r 31a283729295 src/master/service-monitor.c
--- a/src/master/service-monitor.c Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/service-monitor.c Fri Sep 04 17:06:58 2009 -0400
@@ -277,6 +277,7 @@ void services_monitor_reap_children(void
struct service *service;
pid_t pid;
int status;
+ bool service_destroyed;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
process = hash_table_lookup(service_pids, &pid);
@@ -294,10 +295,13 @@ void services_monitor_reap_children(void
} else {
service_process_failure(process, status);
}
+ service_destroyed = service->list->destroyed;
service_process_destroy(process);
- service_monitor_start_extra_avail(service);
-
- if (service->to_throttle == NULL)
- service_monitor_listen_start(service);
- }
-}
+
+ if (!service_destroyed) {
+ service_monitor_start_extra_avail(service);
+ if (service->to_throttle == NULL)
+ service_monitor_listen_start(service);
+ }
+ }
+}
diff -r 199857627883 -r 31a283729295 src/master/service.c
--- a/src/master/service.c Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/service.c Fri Sep 04 17:06:58 2009 -0400
@@ -313,7 +313,7 @@ static int pid_hash_cmp(const void *p1,
*pid1 > *pid2 ? 1 : 0;
}
-static struct service *
+struct service *
service_lookup(struct service_list *service_list, const char *name)
{
struct service *const *services;
@@ -455,22 +455,35 @@ void service_signal(struct service *serv
static void services_kill_timeout(struct service_list *service_list)
{
- struct service *const *services;
+ struct service *const *services, *log_service;
unsigned int i, count;
+ bool sigterm_log;
int sig;
- if (!service_list->sigterm_sent)
+ if (!service_list->sigterm_sent || !service_list->sigterm_sent_to_log)
sig = SIGTERM;
else
sig = SIGKILL;
+ sigterm_log = service_list->sigterm_sent;
service_list->sigterm_sent = TRUE;
i_warning("Processes aren't dying after reload, sending %s.",
sig == SIGTERM ? "SIGTERM" : "SIGKILL");
+ log_service = NULL;
services = array_get(&service_list->services, &count);
- for (i = 0; i < count; i++)
- service_signal(services[i], sig);
+ for (i = 0; i < count; i++) {
+ if (services[i]->type == SERVICE_TYPE_LOG)
+ log_service = services[i];
+ else
+ service_signal(services[i], sig);
+ }
+ /* kill log service later so it could still have a chance of logging
+ something */
+ if (log_service != NULL && sigterm_log) {
+ service_signal(log_service, sig);
+ service_list->sigterm_sent_to_log = TRUE;
+ }
}
void services_destroy(struct service_list *service_list)
@@ -487,6 +500,7 @@ void services_destroy(struct service_lis
services_kill_timeout, service_list);
}
+ service_list->destroyed = TRUE;
service_list_unref(service_list);
}
diff -r 199857627883 -r 31a283729295 src/master/service.h
--- a/src/master/service.h Fri Sep 04 17:06:31 2009 -0400
+++ b/src/master/service.h Fri Sep 04 17:06:58 2009 -0400
@@ -119,7 +119,9 @@ struct service_list {
ARRAY_DEFINE(services, struct service *);
+ unsigned int destroyed:1;
unsigned int sigterm_sent:1;
+ unsigned int sigterm_sent_to_log:1;
};
extern struct hash_table *service_pids;
@@ -147,6 +149,10 @@ void services_throttle_time_sensitives(s
void services_throttle_time_sensitives(struct service_list *list,
unsigned int secs);
+/* Find a service by name. */
+struct service *
+service_lookup(struct service_list *service_list, const char *name);
+
void service_error(struct service *service, const char *format, ...)
ATTR_FORMAT(2, 3);
More information about the dovecot-cvs
mailing list