From: Timo Sirainen Date: Thu, 30 Apr 2009 21:56:47 +0000 (-0400) Subject: master: Fixed logging process related bugs. X-Git-Tag: 2.0.alpha1~870 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=925ef142ae6d9e854cd4e44fbcf2050e744b46be;p=thirdparty%2Fdovecot%2Fcore.git master: Fixed logging process related bugs. --HG-- branch : HEAD --- diff --git a/src/master/service-log.c b/src/master/service-log.c index 6d0abe2b67..7566a52b63 100644 --- a/src/master/service-log.c +++ b/src/master/service-log.c @@ -1,9 +1,12 @@ /* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */ #include "common.h" -#include "fd-close-on-exec.h" #include "array.h" +#include "hash.h" +#include "ioloop.h" +#include "fd-close-on-exec.h" #include "service.h" +#include "service-process.h" #include "service-log.h" #include @@ -62,6 +65,21 @@ int services_log_init(struct service_list *service_list) return 0; } +static void service_remove_log_io_writes(struct service *service) +{ + struct hash_iterate_context *iter; + void *key, *value; + + iter = hash_table_iterate_init(service->list->pids); + while (hash_table_iterate(iter, &key, &value)) { + struct service_process *process = value; + + if (process->io_log_write != NULL) + io_remove(&process->io_log_write); + } + hash_table_iterate_deinit(&iter); +} + void services_log_deinit(struct service_list *service_list) { struct service *const *services; @@ -80,6 +98,7 @@ void services_log_deinit(struct service_list *service_list) } services[i]->log_fd[0] = -1; services[i]->log_fd[1] = -1; + service_remove_log_io_writes(services[i]); } } } diff --git a/src/master/service-process.c b/src/master/service-process.c index 92a96a6cd9..aa13f3c304 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -372,10 +372,37 @@ service_process_create(struct service *service, const char *const *auth_args, return process; } +static void service_process_log_bye(struct service_process *process) +{ + const char *data; + + if (process->service->log_fd[1] == -1) { + /* stopping all services */ + return; + } + + data = t_strdup_printf("\001%c%s bye\n", + LOG_TYPE_OPTION+1, dec2str(process->pid)); + if (write(process->service->log_fd[1], data, strlen(data)) < 0) { + if (errno != EAGAIN) + i_error("write(log process) failed: %m"); + else { + process->io_log_write = + io_add(process->service->log_fd[1], IO_WRITE, + service_process_log_bye, process); + service_process_ref(process); + } + } else { + if (process->io_log_write != NULL) { + io_remove(&process->io_log_write); + service_process_unref(process); + } + } +} + void service_process_destroy(struct service_process *process) { struct service *service = process->service; - const char *data; hash_table_remove(service->list->pids, &process->pid); @@ -398,16 +425,7 @@ void service_process_destroy(struct service_process *process) break; } - data = t_strdup_printf("\001%c%s bye\n", - LOG_TYPE_OPTION+1, dec2str(process->pid)); - if (write(process->service->log_fd[1], data, strlen(data)) < 0) { - if (errno != EAGAIN) - i_error("write(log process) failed: %m"); - else { - //FIXME:process->io_log_write = io_add(); - //return; - } - } + service_process_log_bye(process); process->destroyed = TRUE; service_process_unref(process); @@ -427,6 +445,7 @@ int service_process_unref(struct service_process *process) if (--process->refcount > 0) return TRUE; + i_assert(process->io_log_write == NULL); i_assert(process->destroyed); i_free(process); @@ -543,7 +562,7 @@ static void service_process_log(struct service_process *process, this process's logging */ data = t_strdup_printf("\001%c%s %s %s\n", type+1, my_pid, dec2str(process->pid), str); - if (write_full(process->service->log_fd[1], data, strlen(data)) < 0) { + if (write(process->service->log_fd[1], data, strlen(data)) < 0) { i_error("write(log process) failed: %m"); i_log_type(type, "%s", str); } diff --git a/src/master/service-process.h b/src/master/service-process.h index aca151efce..61b011ea7c 100644 --- a/src/master/service-process.h +++ b/src/master/service-process.h @@ -19,6 +19,8 @@ struct service_process { /* kill the process if it doesn't send initial status notification */ struct timeout *to_status; + /* we're waiting to be able to send "bye" to log process */ + struct io *io_log_write; unsigned int destroyed:1; };