From 25ec2e3e2b919f6bf96604d9a592eeb5ef35930c Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 29 Aug 2010 21:39:49 +0000 Subject: [PATCH] - Add hook_fini() which should be called after fork() from the main hastd process, once it start to use hooks. - Add hook_check_one() in case the caller expects different child processes and once it can recognize it, it will pass pid and status to hook_check_one(). MFC after: 2 weeks Obtained from: Wheel Systems Sp. z o.o. http://www.wheelsystems.com --- sbin/hastd/hooks.c | 80 +++++++++++++++++++++++++++++++++------------- sbin/hastd/hooks.h | 4 +++ 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/sbin/hastd/hooks.c b/sbin/hastd/hooks.c index 11ede20c78f3..eff2f6f95319 100644 --- a/sbin/hastd/hooks.c +++ b/sbin/hastd/hooks.c @@ -82,6 +82,9 @@ struct hookproc { static TAILQ_HEAD(, hookproc) hookprocs; static pthread_mutex_t hookprocs_lock; +static void hook_remove(struct hookproc *hp); +static void hook_free(struct hookproc *hp); + static void descriptors(void) { @@ -147,11 +150,35 @@ void hook_init(void) { + assert(!hooks_initialized); + mtx_init(&hookprocs_lock); TAILQ_INIT(&hookprocs); hooks_initialized = true; } +void +hook_fini(void) +{ + struct hookproc *hp; + + assert(hooks_initialized); + + mtx_lock(&hookprocs_lock); + while ((hp = TAILQ_FIRST(&hookprocs)) != NULL) { + assert(hp->hp_magic == HOOKPROC_MAGIC_ONLIST); + assert(hp->hp_pid > 0); + + hook_remove(hp); + hook_free(hp); + } + mtx_unlock(&hookprocs_lock); + + mtx_destroy(&hookprocs_lock); + TAILQ_INIT(&hookprocs); + hooks_initialized = false; +} + static struct hookproc * hook_alloc(const char *path, char **args) { @@ -237,6 +264,34 @@ hook_find(pid_t pid) return (hp); } +void +hook_check_one(pid_t pid, int status) +{ + struct hookproc *hp; + + mtx_lock(&hookprocs_lock); + hp = hook_find(pid); + if (hp == NULL) { + mtx_unlock(&hookprocs_lock); + pjdlog_debug(1, "Unknown process pid=%u", pid); + return; + } + hook_remove(hp); + mtx_unlock(&hookprocs_lock); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + pjdlog_debug(1, "Hook exited gracefully (pid=%u, cmd=[%s]).", + pid, hp->hp_comm); + } else if (WIFSIGNALED(status)) { + pjdlog_error("Hook was killed (pid=%u, signal=%d, cmd=[%s]).", + pid, WTERMSIG(status), hp->hp_comm); + } else { + pjdlog_error("Hook exited ungracefully (pid=%u, exitcode=%d, cmd=[%s]).", + pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1, + hp->hp_comm); + } + hook_free(hp); +} + void hook_check(bool sigchld) { @@ -250,28 +305,9 @@ hook_check(bool sigchld) /* * If SIGCHLD was received, garbage collect finished processes. */ - while (sigchld && (pid = wait3(&status, WNOHANG, NULL)) > 0) { - mtx_lock(&hookprocs_lock); - hp = hook_find(pid); - if (hp == NULL) { - mtx_unlock(&hookprocs_lock); - pjdlog_warning("Unknown process pid=%u", pid); - continue; - } - hook_remove(hp); - mtx_unlock(&hookprocs_lock); - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - pjdlog_debug(1, "Hook exited gracefully (pid=%u, cmd=[%s]).", - pid, hp->hp_comm); - } else if (WIFSIGNALED(status)) { - pjdlog_error("Hook was killed (pid=%u, signal=%d, cmd=[%s]).", - pid, WTERMSIG(status), hp->hp_comm); - } else { - pjdlog_error("Hook exited ungracefully (pid=%u, exitcode=%d, cmd=[%s]).", - pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1, - hp->hp_comm); - } - hook_free(hp); + if (sigchld) { + while ((pid = wait3(&status, WNOHANG, NULL)) > 0) + hook_check_one(pid, status); } /* diff --git a/sbin/hastd/hooks.h b/sbin/hastd/hooks.h index d18ddc496a2b..5cc57df5e2bc 100644 --- a/sbin/hastd/hooks.h +++ b/sbin/hastd/hooks.h @@ -33,10 +33,14 @@ #ifndef _HOOKS_H_ #define _HOOKS_H_ +#include + #include #include void hook_init(void); +void hook_fini(void); +void hook_check_one(pid_t pid, int status); void hook_check(bool sigchld); void hook_exec(const char *path, ...); void hook_execv(const char *path, va_list ap);