diff options
author | pjd <pjd@FreeBSD.org> | 2010-08-29 21:39:49 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2010-08-29 21:39:49 +0000 |
commit | 9a66bc9a3072bb3aaa48a140ee6c2ef69809de24 (patch) | |
tree | eb91eac7d88da2a0a59338be53956393ff580ed5 /sbin | |
parent | 4a3477caff76069b800be71fe6f98105ad52d6e7 (diff) | |
download | FreeBSD-src-9a66bc9a3072bb3aaa48a140ee6c2ef69809de24.zip FreeBSD-src-9a66bc9a3072bb3aaa48a140ee6c2ef69809de24.tar.gz |
- 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
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/hastd/hooks.c | 80 | ||||
-rw-r--r-- | 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 11ede20..eff2f6f 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) { @@ -238,6 +265,34 @@ hook_find(pid_t pid) } 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) { struct hookproc *hp, *hp2; @@ -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 d18ddc4..5cc57df 100644 --- a/sbin/hastd/hooks.h +++ b/sbin/hastd/hooks.h @@ -33,10 +33,14 @@ #ifndef _HOOKS_H_ #define _HOOKS_H_ +#include <sys/types.h> + #include <stdarg.h> #include <stdbool.h> 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); |