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