# HG changeset patch # User Timo Sirainen # Date 1183214297 -10800 # Node ID f655c4d4a4195091996552001ac93ebc6194cdbf # Parent 77a399a5eb2a4a8bf603edc970b287fb6481a627 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. 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 @@ auth-process.c \ askpass.c \ capabilities-posix.c \ + child-process.c \ dict-process.c \ log.c \ login-process.c \ @@ -35,6 +36,7 @@ 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" @@ -56,6 +58,11 @@ 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; static struct auth_process_group *process_groups; @@ -283,7 +290,7 @@ 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 @@ 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 +#include +#include + +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 diff -r 77a399a5eb2a -r f655c4d4a419 src/master/common.h --- a/src/master/common.h Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/common.h Sat Jun 30 17:38:17 2007 +0300 @@ -4,46 +4,21 @@ struct ip_addr; #include "lib.h" -#include "hash.h" #include "master-settings.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 -}; - extern struct ioloop *ioloop; -extern struct hash_table *pids; extern int null_fd, inetd_login_fd; extern uid_t master_uid; extern char program_path[]; -extern const char *process_names[]; extern char ssl_manual_key_password[]; +extern const char *env_tz; +#ifdef DEBUG +extern bool gdb; +#endif #define IS_INETD() \ (inetd_login_fd != -1) -/* processes */ -#define PID_GET_PROCESS_TYPE(pid) \ - POINTER_CAST_TO(hash_lookup(pids, POINTER_CAST(pid)), pid_t) - -#define PID_ADD_PROCESS_TYPE(pid, type) \ - hash_insert(pids, POINTER_CAST(pid), POINTER_CAST(type)) - -#define PID_REMOVE_PROCESS_TYPE(pid) \ - hash_remove(pids, POINTER_CAST(pid)) - -void child_process_init_env(void); -void client_process_exec(const char *cmd, const char *title); - /* misc */ #define VALIDATE_STR(str) \ validate_str(str, sizeof(str)) diff -r 77a399a5eb2a -r f655c4d4a419 src/master/dict-process.c --- a/src/master/dict-process.c Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/dict-process.c Sat Jun 30 17:38:17 2007 +0300 @@ -7,6 +7,7 @@ #include "fd-close-on-exec.h" #include "env-util.h" #include "log.h" +#include "child-process.h" #include "dict-process.h" #include @@ -16,6 +17,7 @@ #define DICT_SERVER_SOCKET_NAME "dict-server" struct dict_process { + struct child_process process; char *path; int fd; @@ -51,7 +53,7 @@ if (pid != 0) { /* master */ - PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_DICT); + child_process_add(pid, &process->process); log_set_prefix(log, "dict: "); (void)close(log_fd); @@ -155,13 +157,26 @@ process->fd = -1; } +static void +dict_process_destroyed(struct child_process *process, + bool abnormal_exit __attr_unused__) +{ + struct dict_process *p = (struct dict_process *)process; + + (void)dict_process_listen(p); +} + void dict_process_init(void) { process = i_new(struct dict_process, 1); + process->process.type = PROCESS_TYPE_DICT; process->fd = -1; process->path = i_strconcat(settings_root->defaults->base_dir, "/"DICT_SERVER_SOCKET_NAME, NULL); (void)dict_process_listen(process); + + child_process_set_destroy_callback(PROCESS_TYPE_DICT, + dict_process_destroyed); } void dict_process_deinit(void) @@ -173,12 +188,6 @@ i_free(process); } -void dict_process_restart(void) -{ - dict_process_deinit(); - dict_process_init(); -} - void dict_process_kill(void) { if (process->log != NULL) { diff -r 77a399a5eb2a -r f655c4d4a419 src/master/dict-process.h --- a/src/master/dict-process.h Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/dict-process.h Sat Jun 30 17:38:17 2007 +0300 @@ -3,7 +3,6 @@ void dict_process_init(void); void dict_process_deinit(void); -void dict_process_restart(void); void dict_process_kill(void); #endif diff -r 77a399a5eb2a -r f655c4d4a419 src/master/login-process.c --- a/src/master/login-process.c Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/login-process.c Sat Jun 30 17:38:17 2007 +0300 @@ -2,6 +2,7 @@ #include "common.h" #include "ioloop.h" +#include "hash.h" #include "network.h" #include "ostream.h" #include "fdpass.h" @@ -21,6 +22,8 @@ #include struct login_process { + struct child_process process; + struct login_group *group; struct login_process *prev_prelogin, *next_prelogin; int refcount; @@ -51,7 +54,6 @@ static struct io *io_listen; static bool logins_stalled = FALSE; -static struct hash_table *processes; static struct login_group *login_groups; static void login_processes_stall(void); @@ -67,7 +69,7 @@ group = i_new(struct login_group, 1); group->refcount = 1; group->set = set; - group->process_type = set->protocol == MAIL_PROTOCOL_IMAP ? + group->mail_process_type = set->protocol == MAIL_PROTOCOL_IMAP ? PROCESS_TYPE_IMAP : PROCESS_TYPE_POP3; group->next = login_groups; @@ -98,7 +100,8 @@ t_push(); master_reply.success = - create_mail_process(group->process_type, group->set, + create_mail_process(group->mail_process_type, + group->set, request->fd, &request->local_ip, &request->remote_ip, user, args, FALSE); @@ -438,6 +441,7 @@ i_assert(pid != 0); p = i_new(struct login_process, 1); + p->process.type = PROCESS_TYPE_LOGIN; p->group = group; p->refcount = 2; /* once for fd close, another for process exit */ p->pid = pid; @@ -446,9 +450,7 @@ p->output = o_stream_create_file(fd, default_pool, sizeof(struct master_login_reply)*10, FALSE); - - PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); - hash_insert(processes, POINTER_CAST(pid), p); + child_process_add(pid, &p->process); p->state = LOGIN_STATE_LISTENING; @@ -465,7 +467,6 @@ if (p->group != NULL) p->group->processes--; - hash_remove(processes, POINTER_CAST(p->pid)); login_process_unref(p); } @@ -570,7 +571,7 @@ if (set->login_greeting_capability) env_put("GREETING_CAPABILITY=1"); - if (group->process_type == PROCESS_TYPE_IMAP) { + if (group->mail_process_type == PROCESS_TYPE_IMAP) { env_put(t_strconcat("CAPABILITY_STRING=", *set->imap_capability != '\0' ? set->imap_capability : @@ -616,7 +617,7 @@ if (pid != 0) { /* master */ prefix = t_strdup_printf("%s-login: ", - process_names[group->process_type]); + process_names[group->mail_process_type]); log_set_prefix(log, prefix); net_set_nonblock(fd[0], TRUE); @@ -628,7 +629,7 @@ } prefix = t_strdup_printf("master-%s-login: ", - process_names[group->process_type]); + process_names[group->mail_process_type]); log_set_prefix(log, prefix); /* move the listen handle */ @@ -681,13 +682,11 @@ return -1; } -void login_process_destroyed(pid_t pid, bool abnormal_exit) +static void +login_process_destroyed(struct child_process *process, bool abnormal_exit) { - struct login_process *p; + struct login_process *p = (struct login_process *)process; - p = hash_lookup(processes, POINTER_CAST(pid)); - if (p == NULL) - i_panic("Lost login process PID %s", dec2str(pid)); i_assert(!p->inetd_child); if (abnormal_exit) { @@ -706,8 +705,12 @@ void *key, *value; iter = hash_iterate_init(processes); - while (hash_iterate(iter, &key, &value)) - login_process_destroy(value); + while (hash_iterate(iter, &key, &value)) { + struct login_process *p = value; + + if (p->process.type == PROCESS_TYPE_LOGIN) + login_process_destroy(p); + } hash_iterate_deinit(iter); while (login_groups != NULL) { @@ -730,7 +733,7 @@ while (hash_iterate(iter, &key, &value)) { struct login_process *p = value; - if (p->group == group) + if (p->process.type == PROCESS_TYPE_LOGIN && p->group == group) (void)o_stream_send(p->output, &reply, sizeof(reply)); } hash_iterate_deinit(iter); @@ -892,7 +895,9 @@ login_pid_counter = 0; login_groups = NULL; - processes = hash_create(default_pool, default_pool, 128, NULL, NULL); + child_process_set_destroy_callback(PROCESS_TYPE_LOGIN, + login_process_destroyed); + if (!IS_INETD()) { to = timeout_add(1000, login_processes_start_missing, NULL); io_listen = NULL; @@ -906,7 +911,6 @@ void login_processes_deinit(void) { login_processes_destroy_all(); - hash_destroy(processes); if (to != NULL) timeout_remove(&to); diff -r 77a399a5eb2a -r f655c4d4a419 src/master/login-process.h --- a/src/master/login-process.h Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/login-process.h Sat Jun 30 17:38:17 2007 +0300 @@ -1,11 +1,13 @@ #ifndef __LOGIN_PROCESS_H #define __LOGIN_PROCESS_H +#include "child-process.h" + struct login_group { struct login_group *next; int refcount; - enum process_type process_type; + enum process_type mail_process_type; struct settings *set; unsigned int processes; @@ -18,8 +20,6 @@ struct login_process *newest_prelogin_process; }; -void login_process_destroyed(pid_t pid, bool abnormal_exit); - void login_processes_destroy_all(void); void login_processes_init(void); diff -r 77a399a5eb2a -r f655c4d4a419 src/master/mail-process.c --- a/src/master/mail-process.c Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/mail-process.c Sat Jun 30 17:38:17 2007 +0300 @@ -31,6 +31,9 @@ many seconds to finish. */ #define CHDIR_WARN_SECS 10 +static struct child_process imap_child_process = { PROCESS_TYPE_IMAP }; +static struct child_process pop3_child_process = { PROCESS_TYPE_POP3 }; + static unsigned int mail_process_count = 0; static bool validate_uid_gid(struct settings *set, uid_t uid, gid_t gid, @@ -439,6 +442,9 @@ int ret, log_fd, nice, chdir_errno; bool home_given, nfs_check; + i_assert(process_type == PROCESS_TYPE_IMAP || + process_type == PROCESS_TYPE_POP3); + // FIXME: per-group if (mail_process_count == set->max_mail_processes) { i_error("Maximum number of mail processes exceeded"); @@ -554,7 +560,10 @@ mail_process_count++; if (!dump_capability) { log_set_prefix(log, str_c(str)); - PID_ADD_PROCESS_TYPE(pid, process_type); + child_process_add(pid, + process_type == PROCESS_TYPE_IMAP ? + &imap_child_process : + &pop3_child_process); } (void)close(log_fd); return TRUE; @@ -709,7 +718,17 @@ return FALSE; } -void mail_process_destroyed(pid_t pid __attr_unused__) +static void +mail_process_destroyed(struct child_process *process __attr_unused__, + bool abnormal_exit __attr_unused__) { mail_process_count--; } + +void mail_processes_init(void) +{ + child_process_set_destroy_callback(PROCESS_TYPE_IMAP, + mail_process_destroyed); + child_process_set_destroy_callback(PROCESS_TYPE_POP3, + mail_process_destroyed); +} diff -r 77a399a5eb2a -r f655c4d4a419 src/master/mail-process.h --- a/src/master/mail-process.h Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/mail-process.h Sat Jun 30 17:38:17 2007 +0300 @@ -1,6 +1,8 @@ #ifndef __MAIL_PROCESS_H #define __MAIL_PROCESS_H +#include "child-process.h" + struct login_group; struct auth_master_reply; @@ -13,6 +15,6 @@ const char *user, const char *const *args, bool dump_capability); -void mail_process_destroyed(pid_t pid); +void mail_processes_init(void); #endif diff -r 77a399a5eb2a -r f655c4d4a419 src/master/main.c --- a/src/master/main.c Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/main.c Sat Jun 30 17:38:17 2007 +0300 @@ -24,30 +24,17 @@ #include #include #include -#include - -const char *process_names[PROCESS_TYPE_MAX] = { - "unknown", - "auth", - "auth-worker", - "login", - "imap", - "pop3", - "ssl-build-param", - "dict" -}; static const char *configfile = SYSCONFDIR "/" PACKAGE ".conf"; -static const char *env_tz; struct ioloop *ioloop; -struct hash_table *pids; int null_fd = -1, inetd_login_fd; uid_t master_uid; char program_path[PATH_MAX]; char ssl_manual_key_password[100]; +const char *env_tz; #ifdef DEBUG -static bool gdb; +bool gdb; #endif static void listen_fds_open(bool retry); @@ -65,50 +52,6 @@ return FALSE; } -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 void set_logfile(struct settings *set) { int facility; @@ -172,91 +115,6 @@ set_logfile(settings_root->defaults); } -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__) -{ - const char *process_type_name, *msg; - pid_t pid; - int status, process_type; - bool abnormal_exit; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - /* get the type and remove from hash */ - process_type = PID_GET_PROCESS_TYPE(pid); - if (process_type != PROCESS_TYPE_UNKNOWN) - PID_REMOVE_PROCESS_TYPE(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)); - } - - switch (process_type) { - case PROCESS_TYPE_LOGIN: - login_process_destroyed(pid, abnormal_exit); - break; - case PROCESS_TYPE_IMAP: - case PROCESS_TYPE_POP3: - mail_process_destroyed(pid); - break; - case PROCESS_TYPE_SSL_PARAM: - ssl_parameter_process_destroyed(abnormal_exit); - break; - case PROCESS_TYPE_DICT: - dict_process_restart(); - break; - } - } - - if (pid == -1 && errno != EINTR && errno != ECHILD) - i_warning("waitpid() failed: %m"); -} - static void resolve_ip(const char *set_name, const char *name, struct ip_addr *ip, unsigned int *port) { @@ -598,14 +456,13 @@ lib_signals_set_handler(SIGHUP, TRUE, sig_reload_settings, NULL); lib_signals_set_handler(SIGUSR1, TRUE, sig_reopen_logs, NULL); - pids = hash_create(default_pool, default_pool, 128, NULL, NULL); - lib_signals_set_handler(SIGCHLD, TRUE, sigchld_handler, NULL); - + child_processes_init(); log_init(); ssl_init(); dict_process_init(); auth_processes_init(); login_processes_init(); + mail_processes_init(); create_pid_file(t_strconcat(settings_root->defaults->base_dir, "/master.pid", NULL)); @@ -616,20 +473,15 @@ (void)unlink(t_strconcat(settings_root->defaults->base_dir, "/master.pid", NULL)); - /* make sure we log if child processes died unexpectedly */ - sigchld_handler(SIGCHLD, NULL); - login_processes_deinit(); auth_processes_deinit(); dict_process_deinit(); ssl_deinit(); - - lib_signals_unset_handler(SIGCHLD, sigchld_handler, NULL); + child_processes_deinit(); if (close(null_fd) < 0) i_error("close(null_fd) failed: %m"); - hash_destroy(pids); lib_signals_deinit(); log_deinit(); closelog(); diff -r 77a399a5eb2a -r f655c4d4a419 src/master/ssl-init.c --- a/src/master/ssl-init.c Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/ssl-init.c Sat Jun 30 17:38:17 2007 +0300 @@ -5,6 +5,7 @@ #include "env-util.h" #include "file-copy.h" #include "log.h" +#include "child-process.h" #include "ssl-init.h" #ifdef HAVE_SSL @@ -16,6 +17,9 @@ #include #include +static struct child_process ssl_param_child_process = + { PROCESS_TYPE_SSL_PARAM }; + static struct timeout *to; static char *generating_path = NULL; @@ -46,7 +50,7 @@ /* parent */ i_assert(generating_path == NULL); generating_path = i_strdup(fname); - PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_SSL_PARAM); + child_process_add(pid, &ssl_param_child_process); (void)close(log_fd); return; } @@ -61,7 +65,9 @@ i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", binpath); } -void ssl_parameter_process_destroyed(bool abnormal_exit) +static void +ssl_parameter_process_destroyed(struct child_process *process __attr_unused__, + bool abnormal_exit) { if (!abnormal_exit) { if (file_copy(SSL_PARAMETERS_PERM_PATH, @@ -155,6 +161,9 @@ { generating_path = NULL; + child_process_set_destroy_callback(PROCESS_TYPE_SSL_PARAM, + ssl_parameter_process_destroyed); + /* check every 10 mins */ to = timeout_add(600 * 1000, check_parameters_file_timeout, NULL); diff -r 77a399a5eb2a -r f655c4d4a419 src/master/ssl-init.h --- a/src/master/ssl-init.h Sat Jun 30 00:48:10 2007 +0300 +++ b/src/master/ssl-init.h Sat Jun 30 17:38:17 2007 +0300 @@ -3,8 +3,6 @@ #define SSL_PARAMETERS_FILENAME "ssl-parameters.dat" -void ssl_parameter_process_destroyed(bool abnormal_exit); - void ssl_check_parameters_file(void); void _ssl_generate_parameters(int fd, const char *fname);