dovecot: Moved child process handling to child-process.[ch]. The...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jun 30 17:38:29 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/f655c4d4a419
changeset: 5843:f655c4d4a419
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jun 30 17:38:17 2007 +0300
description:
Moved child process handling to child-process.[ch]. The hash table now uses
pointers to structures instead of a casted process type. This allowed
removing another login-processes hash table.

diffstat:

14 files changed, 324 insertions(+), 224 deletions(-)
src/master/Makefile.am     |    2 
src/master/auth-process.c  |   11 ++
src/master/child-process.c |  184 ++++++++++++++++++++++++++++++++++++++++++++
src/master/child-process.h |   40 +++++++++
src/master/common.h        |   33 -------
src/master/dict-process.c  |   23 +++--
src/master/dict-process.h  |    1 
src/master/login-process.c |   48 ++++++-----
src/master/login-process.h |    6 -
src/master/mail-process.c  |   23 +++++
src/master/mail-process.h  |    4 
src/master/main.c          |  158 +------------------------------------
src/master/ssl-init.c      |   13 ++-
src/master/ssl-init.h      |    2 

diffs (truncated from 977 to 300 lines):

diff -r 77a399a5eb2a -r f655c4d4a419 src/master/Makefile.am
--- a/src/master/Makefile.am	Sat Jun 30 00:48:10 2007 +0300
+++ b/src/master/Makefile.am	Sat Jun 30 17:38:17 2007 +0300
@@ -22,6 +22,7 @@ dovecot_SOURCES = \
 	auth-process.c \
 	askpass.c \
 	capabilities-posix.c \
+	child-process.c \
 	dict-process.c \
 	log.c \
 	login-process.c \
@@ -35,6 +36,7 @@ noinst_HEADERS = \
 	auth-process.h \
 	askpass.h \
 	capabilities.h \
+	child-process.h \
 	dict-process.h \
 	common.h \
 	log.h \
diff -r 77a399a5eb2a -r f655c4d4a419 src/master/auth-process.c
--- a/src/master/auth-process.c	Sat Jun 30 00:48:10 2007 +0300
+++ b/src/master/auth-process.c	Sat Jun 30 17:38:17 2007 +0300
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "hash.h"
 #include "ioloop.h"
 #include "env-util.h"
 #include "fd-close-on-exec.h"
@@ -12,6 +13,7 @@
 #include "restrict-access.h"
 #include "restrict-process-size.h"
 #include "auth-process.h"
+#include "child-process.h"
 #include "../auth/auth-master-interface.h"
 #include "log.h"
 
@@ -55,6 +57,11 @@ struct auth_process {
 };
 
 bool have_initialized_auth_processes = FALSE;
+
+static struct child_process auth_child_process =
+	{ PROCESS_TYPE_AUTH };
+static struct child_process auth_worker_child_process =
+	{ PROCESS_TYPE_AUTH_WORKER };
 
 static struct timeout *to;
 static unsigned int auth_tag;
@@ -283,7 +290,7 @@ auth_process_new(pid_t pid, int fd, stru
 	const char *path, *handshake;
 
 	if (pid != 0)
-		PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH);
+		child_process_add(pid, &auth_child_process);
 
 	p = i_new(struct auth_process, 1);
 	p->group = group;
@@ -603,7 +610,7 @@ static int create_auth_worker(struct aut
 
 	if (pid != 0) {
 		/* master */
-		PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH_WORKER);
+		child_process_add(pid, &auth_worker_child_process);
 		prefix = t_strdup_printf("auth-worker(%s): ",
 					 process->group->set->name);
 		log_set_prefix(log, prefix);
diff -r 77a399a5eb2a -r f655c4d4a419 src/master/child-process.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/master/child-process.c	Sat Jun 30 17:38:17 2007 +0300
@@ -0,0 +1,184 @@
+/* Copyright (C) 2002-2007 Timo Sirainen */
+
+#include "common.h"
+#include "lib-signals.h"
+#include "hash.h"
+#include "env-util.h"
+#include "syslog-util.h"
+#include "child-process.h"
+
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/wait.h>
+
+const char *process_names[PROCESS_TYPE_MAX] = {
+	"unknown",
+	"auth",
+	"auth-worker",
+	"login",
+	"imap",
+	"pop3",
+	"ssl-build-param",
+	"dict"
+};
+
+struct hash_table *processes;
+static child_process_destroy_callback_t *destroy_callbacks[PROCESS_TYPE_MAX];
+
+struct child_process *child_process_lookup(pid_t pid)
+{
+	return hash_lookup(processes, POINTER_CAST(pid));
+}
+
+void child_process_add(pid_t pid, struct child_process *process)
+{
+	hash_insert(processes, POINTER_CAST(pid), process);
+}
+
+void child_process_remove(pid_t pid)
+{
+	hash_remove(processes, POINTER_CAST(pid));
+}
+
+void child_process_init_env(void)
+{
+	int facility;
+
+	/* remove all environment, we don't need them */
+	env_clean();
+
+	/* we'll log through master process */
+	env_put("LOG_TO_MASTER=1");
+	if (env_tz != NULL)
+		env_put(t_strconcat("TZ=", env_tz, NULL));
+
+	if (settings_root == NULL ||
+	    !syslog_facility_find(settings_root->defaults->syslog_facility,
+				  &facility))
+		facility = LOG_MAIL;
+	env_put(t_strdup_printf("SYSLOG_FACILITY=%d", facility));
+
+	if (settings_root != NULL && !settings_root->defaults->version_ignore)
+		env_put("DOVECOT_VERSION="PACKAGE_VERSION);
+#ifdef DEBUG
+	if (gdb) env_put("GDB=1");
+#endif
+}
+
+void client_process_exec(const char *cmd, const char *title)
+{
+	const char *executable, *p, **argv;
+
+	/* very simple argument splitting. */
+	if (*title == '\0')
+		argv = t_strsplit(cmd, " ");
+	else
+		argv = t_strsplit(t_strconcat(cmd, " ", title, NULL), " ");
+
+	executable = argv[0];
+
+	/* hide the path, it's ugly */
+	p = strrchr(argv[0], '/');
+	if (p != NULL) argv[0] = p+1;
+
+	execv(executable, (char **)argv);
+}
+
+static const char *get_exit_status_message(enum fatal_exit_status status)
+{
+	switch (status) {
+	case FATAL_LOGOPEN:
+		return "Can't open log file";
+	case FATAL_LOGWRITE:
+		return "Can't write to log file";
+	case FATAL_LOGERROR:
+		return "Internal logging error";
+	case FATAL_OUTOFMEM:
+		return "Out of memory";
+	case FATAL_EXEC:
+		return "exec() failed";
+
+	case FATAL_DEFAULT:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+static void sigchld_handler(int signo __attr_unused__,
+			    void *context __attr_unused__)
+{
+	struct child_process *process;
+	const char *process_type_name, *msg;
+	enum process_type process_type;
+	pid_t pid;
+	int status;
+	bool abnormal_exit;
+
+	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+		/* get the type and remove from hash */
+		process = child_process_lookup(pid);
+		if (process == NULL)
+			process_type = PROCESS_TYPE_UNKNOWN;
+		else {
+			process_type = process->type;
+			child_process_remove(pid);
+		}
+		abnormal_exit = TRUE;
+
+		/* write errors to syslog */
+		process_type_name = process_names[process_type];
+		if (WIFEXITED(status)) {
+			status = WEXITSTATUS(status);
+			if (status == 0) {
+				abnormal_exit = FALSE;
+				if (process_type == PROCESS_TYPE_UNKNOWN) {
+					i_error("unknown child %s exited "
+						"successfully", dec2str(pid));
+				}
+			} else if (status == 1 &&
+				   process_type == PROCESS_TYPE_SSL_PARAM) {
+				/* kludgy. hide this failure. */
+			} else {
+				msg = get_exit_status_message(status);
+				msg = msg == NULL ? "" :
+					t_strconcat(" (", msg, ")", NULL);
+				i_error("child %s (%s) returned error %d%s",
+					dec2str(pid), process_type_name,
+					status, msg);
+			}
+		} else if (WIFSIGNALED(status)) {
+			i_error("child %s (%s) killed with signal %d",
+				dec2str(pid), process_type_name,
+				WTERMSIG(status));
+		}
+
+		if (destroy_callbacks[process_type] != NULL)
+			destroy_callbacks[process_type](process, abnormal_exit);
+	}
+
+	if (pid == -1 && errno != EINTR && errno != ECHILD)
+		i_warning("waitpid() failed: %m");
+}
+
+void child_process_set_destroy_callback(enum process_type type,
+					child_process_destroy_callback_t *cb)
+{
+	i_assert(type < PROCESS_TYPE_MAX);
+
+	destroy_callbacks[type] = cb;
+}
+
+void child_processes_init(void)
+{
+	processes = hash_create(default_pool, default_pool, 128, NULL, NULL);
+	lib_signals_set_handler(SIGCHLD, TRUE, sigchld_handler, NULL);
+}
+
+void child_processes_deinit(void)
+{
+	/* make sure we log if child processes died unexpectedly */
+	sigchld_handler(SIGCHLD, NULL);
+	lib_signals_unset_handler(SIGCHLD, sigchld_handler, NULL);
+	hash_destroy(processes);
+}
diff -r 77a399a5eb2a -r f655c4d4a419 src/master/child-process.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/master/child-process.h	Sat Jun 30 17:38:17 2007 +0300
@@ -0,0 +1,40 @@
+#ifndef __CHILD_PROCESS_H
+#define __CHILD_PROCESS_H
+
+enum process_type {
+	PROCESS_TYPE_UNKNOWN,
+	PROCESS_TYPE_AUTH,
+	PROCESS_TYPE_AUTH_WORKER,
+	PROCESS_TYPE_LOGIN,
+	PROCESS_TYPE_IMAP,
+	PROCESS_TYPE_POP3,
+	PROCESS_TYPE_SSL_PARAM,
+	PROCESS_TYPE_DICT,
+
+	PROCESS_TYPE_MAX
+};
+
+struct child_process {
+	enum process_type type;
+};
+
+typedef void child_process_destroy_callback_t(struct child_process *,
+					      bool abnormal_exit);
+
+extern const char *process_names[];
+extern struct hash_table *processes;
+
+struct child_process *child_process_lookup(pid_t pid);
+void child_process_add(pid_t pid, struct child_process *process);
+void child_process_remove(pid_t pid);
+
+void child_process_init_env(void);
+void client_process_exec(const char *cmd, const char *title);
+
+void child_process_set_destroy_callback(enum process_type type,
+					child_process_destroy_callback_t *cb);
+
+void child_processes_init(void);
+void child_processes_deinit(void);
+
+#endif


More information about the dovecot-cvs mailing list