Mercurial > dovecot > core-2.2
changeset 9876:31a283729295 HEAD
master: Several fixes to handling SIGHUPs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Sep 2009 17:06:58 -0400 |
parents | 199857627883 |
children | 3de6af0eb499 |
files | src/master/common.h src/master/main.c src/master/service-auth-server.c src/master/service-listen.c src/master/service-monitor.c src/master/service.c src/master/service.h |
diffstat | 7 files changed, 71 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- 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 core_dumps_disabled; extern int null_fd; +extern struct service_list *services; void process_exec(const char *cmd, const char *extra_args[]) ATTR_NORETURN;
--- 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 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 */
--- 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 @@ 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 @@ 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;
--- 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 @@ 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 @@ 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 */
--- 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 @@ 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 @@ } 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); + } } }
--- 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 @@ *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 @@ 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 @@ services_kill_timeout, service_list); } + service_list->destroyed = TRUE; service_list_unref(service_list); }
--- 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 @@ 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(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);