dovecot-2.0: master: Support reloading configuration.

dovecot at dovecot.org dovecot at dovecot.org
Sat Aug 15 01:14:58 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/da330a07e45c
changeset: 9794:da330a07e45c
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Aug 14 18:14:21 2009 -0400
description:
master: Support reloading configuration.

diffstat:

10 files changed, 186 insertions(+), 76 deletions(-)
src/lib-master/master-service-settings.c |   22 +++--
src/lib-master/master-service-settings.h |    6 +
src/master/main.c                        |   51 +++++++-----
src/master/master-settings.h             |    3 
src/master/service-auth-source.c         |    2 
src/master/service-monitor.c             |    6 -
src/master/service-monitor.h             |    2 
src/master/service-process.c             |   20 ++--
src/master/service.c                     |  125 +++++++++++++++++++++++-------
src/master/service.h                     |   25 +++++-

diffs (truncated from 621 to 300 lines):

diff -r d7ccdbb58a03 -r da330a07e45c src/lib-master/master-service-settings.c
--- a/src/lib-master/master-service-settings.c	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/lib-master/master-service-settings.c	Fri Aug 14 18:14:21 2009 -0400
@@ -97,15 +97,13 @@ master_service_exec_config(struct master
 }
 
 static int
-master_service_read_config(struct master_service *service,
+master_service_read_config(struct master_service *service, const char *path,
 			   const struct master_service_settings_input *input,
 			   const char **error_r)
 {
-	const char *path;
 	struct stat st;
 	int fd, ret;
 
-	path = master_service_get_config_path(service);
 	if (service->config_fd != -1) {
 		fd = service->config_fd;
 		service->config_fd = -1;
@@ -184,19 +182,22 @@ int master_service_settings_read(struct 
 	const struct setting_parser_info *tmp_root;
 	struct setting_parser_context *parser;
 	struct istream *istream;
-	const char *error, *env, *const *keys;
+	const char *path, *error, *env, *const *keys;
 	void **sets;
 	unsigned int i;
 	int ret, fd = -1;
 
 	if (getenv("DOVECONF_ENV") == NULL && !service->default_settings) {
-		fd = master_service_read_config(service, input, error_r);
+		path = input->config_path != NULL ? input->config_path :
+			master_service_get_config_path(service);
+		fd = master_service_read_config(service, path, input, error_r);
 		if (fd == -1)
 			return -1;
 	}
 
 	if (service->set_pool != NULL) {
-		settings_parser_deinit(&service->set_parser);
+		if (service->set_parser != NULL)
+			settings_parser_deinit(&service->set_parser);
 		p_clear(service->set_pool);
 	} else {
 		service->set_pool =
@@ -289,6 +290,15 @@ int master_service_settings_read_simple(
 	return master_service_settings_read(service, &input, error_r);
 }
 
+pool_t master_service_settings_detach(struct master_service *service)
+{
+	pool_t pool = service->set_pool;
+
+	settings_parser_deinit(&service->set_parser);
+	service->set_pool = NULL;
+	return pool;
+}
+
 const struct master_service_settings *
 master_service_settings_get(struct master_service *service)
 {
diff -r d7ccdbb58a03 -r da330a07e45c src/lib-master/master-service-settings.h
--- a/src/lib-master/master-service-settings.h	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/lib-master/master-service-settings.h	Fri Aug 14 18:14:21 2009 -0400
@@ -18,6 +18,7 @@ struct master_service_settings_input {
 struct master_service_settings_input {
 	const struct setting_parser_info **roots;
 	const struct dynamic_settings_parser *dyn_parsers;
+	const char *config_path;
 	bool preserve_home;
 
 	const char *module;
@@ -34,6 +35,11 @@ int master_service_settings_read_simple(
 int master_service_settings_read_simple(struct master_service *service,
 					const struct setting_parser_info **roots,
 					const char **error_r);
+/* destroy settings parser and clear service's set_pool, so that
+   master_service_settings_read*() can be called without freeing memory used
+   by existing settings structures. */
+pool_t master_service_settings_detach(struct master_service *service);
+
 const struct master_service_settings *
 master_service_settings_get(struct master_service *service);
 void **master_service_settings_get_others(struct master_service *service);
diff -r d7ccdbb58a03 -r da330a07e45c src/master/main.c
--- a/src/master/main.c	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/main.c	Fri Aug 14 18:14:21 2009 -0400
@@ -27,6 +27,7 @@
 
 #define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
 
+#define MASTER_SERVICE_NAME "master"
 #define FATAL_FILENAME "master-fatal.lastlog"
 #define MASTER_PID_FILE_NAME "master.pid"
 #define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
@@ -41,8 +42,12 @@ static char *pidfile_path;
 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 */
+
+static const struct setting_parser_info *set_roots[] = {
+	&master_setting_parser_info,
+	NULL
+};
 
 void process_exec(const char *cmd, const char *extra_args[])
 {
@@ -304,32 +309,41 @@ sig_settings_reload(const siginfo_t *si 
 sig_settings_reload(const siginfo_t *si ATTR_UNUSED,
 		    void *context ATTR_UNUSED)
 {
-	struct master_settings *new_set;
+	struct master_service_settings_input input;
+	const struct master_settings *set;
+	void **sets;
 	struct service_list *new_services;
 	const char *error;
-	pool_t pool;
 
 	/* see if hostname changed */
 	hostpid_init();
 
-#if 0 // FIXME
-	/* FIXME: this loses process structures for existing processes.
-	   figure out something. */
-	new_set = master_settings_read(pool, config_binary, config_path);
-	new_services = new_set == NULL ? NULL :
-		services_create(new_set, child_process_env, &error);
-#endif
-	if (new_services == NULL) {
+	memset(&input, 0, sizeof(input));
+	input.roots = set_roots;
+	input.module = MASTER_SERVICE_NAME;
+	input.config_path = services_get_config_socket_path(services);
+	if (master_service_settings_read(master_service, &input, &error) < 0) {
+		i_error("Error reading configuration: %s", error);
+		return;
+	}
+	sets = master_service_settings_get_others(master_service);
+	set = sets[0];
+
+	if (services_create(set, child_process_env,
+			    &new_services, &error) < 0) {
 		/* new configuration is invalid, keep the old */
 		i_error("Config reload failed: %s", error);
 		return;
 	}
+	new_services->config->config_file_path =
+		p_strdup(new_services->pool,
+			 services->config->config_file_path);
 
 	/* switch to new configuration. */
 	(void)services_listen_using(new_services, services);
 	services_destroy(services);
+
 	services = new_services;
-
         services_monitor_start(services);
 }
 
@@ -342,7 +356,7 @@ static void
 static void
 sig_reap_children(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
 {
-	services_monitor_reap_children(services);
+	services_monitor_reap_children();
 }
 
 static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
@@ -404,6 +418,7 @@ static void main_deinit(void)
 	i_free(pidfile_path);
 
 	services_destroy(services);
+	service_pids_deinit();
 }
 
 static const char *get_full_config_path(struct service_list *list)
@@ -571,10 +586,6 @@ static void print_build_options(void)
 
 int main(int argc, char *argv[])
 {
-	static const struct setting_parser_info *set_roots[] = {
-		&master_setting_parser_info,
-		NULL
-	};
 	struct master_settings *set;
 	unsigned int child_process_env_idx = 0;
 	const char *getopt_str, *error, *env_tz, *doveconf_arg = NULL;
@@ -589,7 +600,7 @@ int main(int argc, char *argv[])
 	else
 		child_process_env[child_process_env_idx++] = "GDB=1";
 #endif
-	master_service = master_service_init("master",
+	master_service = master_service_init(MASTER_SERVICE_NAME,
 				MASTER_SERVICE_FLAG_STANDALONE |
 				MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR,
 				argc, argv);
@@ -721,8 +732,8 @@ int main(int argc, char *argv[])
 
 	/* create service structures from settings. if there are any errors in
 	   service configuration we'll catch it here. */
-	services = services_create(set, child_process_env, &error);
-	if (services == NULL)
+	service_pids_init();
+	if (services_create(set, child_process_env, &services, &error) < 0)
 		i_fatal("%s", error);
 
 	services->config->config_file_path = get_full_config_path(services);
diff -r d7ccdbb58a03 -r da330a07e45c src/master/master-settings.h
--- a/src/master/master-settings.h	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/master-settings.h	Fri Aug 14 18:14:21 2009 -0400
@@ -61,9 +61,6 @@ struct master_settings {
 
 extern struct setting_parser_info master_setting_parser_info;
 
-struct master_settings *
-master_settings_read(pool_t pool, const char *config_binary,
-		     const char *config_path);
 bool master_settings_do_fixes(const struct master_settings *set);
 
 #endif
diff -r d7ccdbb58a03 -r da330a07e45c src/master/service-auth-source.c
--- a/src/master/service-auth-source.c	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/service-auth-source.c	Fri Aug 14 18:14:21 2009 -0400
@@ -204,7 +204,7 @@ service_process_auth_source_input(struct
 	fd_close_on_exec(client_fd, TRUE);
 
 	/* we have a request. check its validity. */
-	auth_process = hash_table_lookup(service->list->pids, &req.auth_pid);
+	auth_process = hash_table_lookup(service_pids, &req.auth_pid);
 	if (auth_process == NULL) {
 		service_error(service, "authentication request for unknown "
 			      "auth server PID %s", dec2str(req.auth_pid));
diff -r d7ccdbb58a03 -r da330a07e45c src/master/service-monitor.c
--- a/src/master/service-monitor.c	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/service-monitor.c	Fri Aug 14 18:14:21 2009 -0400
@@ -44,7 +44,7 @@ static void service_status_input(struct 
 		break;
 	}
 
-	process = hash_table_lookup(service->list->pids, &status.pid);
+	process = hash_table_lookup(service_pids, &status.pid);
 	if (process == NULL) {
 		/* we've probably wait()ed it away already. ignore */
 		return;
@@ -239,7 +239,7 @@ static void service_process_failure(stru
 		service_process_notify_add(service->list->anvil_kills, process);
 }
 
-void services_monitor_reap_children(struct service_list *service_list)
+void services_monitor_reap_children(void)
 {
 	struct service_process *process;
 	struct service *service;
@@ -247,7 +247,7 @@ void services_monitor_reap_children(stru
 	int status;
 
 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-		process = hash_table_lookup(service_list->pids, &pid);
+		process = hash_table_lookup(service_pids, &pid);
 		if (process == NULL) {
 			i_error("waitpid() returned unknown PID %s",
 				dec2str(pid));
diff -r d7ccdbb58a03 -r da330a07e45c src/master/service-monitor.h
--- a/src/master/service-monitor.h	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/service-monitor.h	Fri Aug 14 18:14:21 2009 -0400
@@ -8,7 +8,7 @@ void services_monitor_stop(struct servic
 void services_monitor_stop(struct service_list *service_list);
 
 /* Call after SIGCHLD has been detected */
-void services_monitor_reap_children(struct service_list *service_list);
+void services_monitor_reap_children(void);
 
 void service_monitor_stop(struct service *service);
 void service_monitor_listen_start(struct service *service);
diff -r d7ccdbb58a03 -r da330a07e45c src/master/service-process.c
--- a/src/master/service-process.c	Fri Aug 14 18:13:35 2009 -0400
+++ b/src/master/service-process.c	Fri Aug 14 18:14:21 2009 -0400
@@ -367,10 +367,9 @@ static void
 static void
 service_process_setup_environment(struct service *service, unsigned int uid)
 {
-	const struct master_service_settings *set;
-        struct service_listener *const *listeners;
+	const struct master_service_settings *set = service->list->service_set;
 	const char *const *p;
-	unsigned int limit, count;
+	unsigned int limit;
 
 	/* remove all environment, and put back what we need */
 	env_clean();
@@ -385,7 +384,6 @@ service_process_setup_environment(struct
 	case SERVICE_TYPE_LOG:
 		/* give the log's configuration directly, so it won't depend
 		   on config process */
-		set = master_service_settings_get(master_service);
 		env_put("DOVECONF_ENV=1");


More information about the dovecot-cvs mailing list