diff options
Diffstat (limited to 'server/monitor.c')
-rw-r--r-- | server/monitor.c | 206 |
1 files changed, 100 insertions, 106 deletions
diff --git a/server/monitor.c b/server/monitor.c index 93ebeddc..2d3283fd 100644 --- a/server/monitor.c +++ b/server/monitor.c @@ -19,55 +19,88 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> #include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <string.h> +#include <sys/wait.h> #include <sys/time.h> +#include <time.h> #include "../events/events.h" #include "util/util.h" #include "service.h" +#include "confdb/confdb.h" struct mt_ctx { - struct task_server *task; - struct fd_event *test_fde; - int test_fd; + struct event_context *ev; + struct confdb_ctx *cdb; + char **services; }; -static void set_nonblocking(int fd) -{ - unsigned v; - v = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, v | O_NONBLOCK); -} +struct mt_srv { + const char *name; + struct mt_ctx *mt_ctx; + pid_t pid; + time_t last_restart; + int restarts; +}; -static void set_close_on_exec(int fd) +static void set_tasks_checker(struct mt_srv *srv); + +static void tasks_check_handler(struct event_context *ev, + struct timed_event *te, + struct timeval t, void *ptr) { - unsigned v; - v = fcntl(fd, F_GETFD, 0); - fcntl(fd, F_SETFD, v | FD_CLOEXEC); -} + struct mt_srv *srv = talloc_get_type(ptr, struct mt_srv); + time_t now = time(NULL); + int status; + pid_t pid; + int ret; + + pid = waitpid(srv->pid, &status, WNOHANG); + if (pid == 0) { + set_tasks_checker(srv); + return; + } -static void set_test_timed_event(struct event_context *ev, - struct mt_ctx *ctx); + if (pid != srv->pid) { + DEBUG(1, ("bad return (%d) from waitpid() waiting for %d\n", + pid, srv->pid)); + /* TODO: what do we do now ? */ + } -static void test_timed_handler(struct event_context *ev, - struct timed_event *te, - struct timeval t, void *ptr) -{ - struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx); + if (WIFEXITED(status)) { /* children exited on it's own ?? */ + /* TODO: check configuration to see if it was removed + * from the list of process to run */ + DEBUG(0,("Process [%s] exited on it's own ?!\n", srv->name)); + } - fprintf(stdout, "."); - fflush(stdout); + if (srv->last_restart != 0) { + if ((now - srv->last_restart) > 30) { /* TODO: get val from config */ + /* it was long ago reset restart threshold */ + srv->restarts = 0; + } + } + + /* restart the process */ + if (srv->restarts < 3) { /* TODO: get val from config */ + + ret = server_service_init(srv->name, srv->mt_ctx->ev, &srv->pid); + if (ret != EOK) { + DEBUG(0,("Failed to restart service '%s'\n", srv->name)); + talloc_free(srv); + return; + } - set_test_timed_event(ev, ctx); + srv->restarts++; + srv->last_restart = now; + + set_tasks_checker(srv); + return; + } + + DEBUG(0, ("Process [%s], definitely stopped!\n", srv->name)); + talloc_free(srv); } -static void set_test_timed_event(struct event_context *ev, - struct mt_ctx *ctx) +static void set_tasks_checker(struct mt_srv *srv) { struct timed_event *te = NULL; struct timeval tv; @@ -75,94 +108,55 @@ static void set_test_timed_event(struct event_context *ev, gettimeofday(&tv, NULL); tv.tv_sec += 2; tv.tv_usec = 0; - te = event_add_timed(ev, ctx, tv, test_timed_handler, ctx); + te = event_add_timed(srv->mt_ctx->ev, srv, tv, tasks_check_handler, srv); if (te == NULL) { - DEBUG(0, ("failed to add event!\n")); - task_server_terminate(ctx->task, "fatal error initializing service\n"); - } -} - -static void test_fd_handler(struct event_context *ev, - struct fd_event *fde, - uint16_t flags, void *ptr) -{ - /* accept and close */ - struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx); - struct sockaddr_un addr; - socklen_t len; - int fd; - - memset(&addr, 0, sizeof(addr)); - len = sizeof(addr); - fd = accept(ctx->test_fd, (struct sockaddr *)&addr, &len); - if (fd == -1) { - return; + DEBUG(0, ("failed to add event, monitor offline for [%s]!\n", + srv->name)); + /* FIXME: shutdown ? */ } - - close(fd); - return; } -/* create a unix socket and listen to it */ -static void set_test_fd_event(struct event_context *ev, - struct mt_ctx *ctx) +int start_monitor(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + struct confdb_ctx *cdb) { - struct sockaddr_un addr; - const char *sock_name = "/tmp/foo/test_sock"; - - /* make sure we have no old sockets around */ - unlink(sock_name); + struct mt_ctx *ctx; + struct mt_srv *srv; + int ret, i; - ctx->test_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (ctx->test_fd == -1) { - return; + ctx = talloc_zero(mem_ctx, struct mt_ctx); + if (!ctx) { + DEBUG(0, ("fatal error initializing monitor!\n")); + return ENOMEM; } + ctx->ev = event_ctx; - set_nonblocking(ctx->test_fd); - set_close_on_exec(ctx->test_fd); + ret = confdb_get_param(cdb, mem_ctx, "config.services", + "activeServices", &ctx->services); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path)); - - if (bind(ctx->test_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - DEBUG(0,("Unable to bind on socket '%s'\n", sock_name)); - goto failed; - } - if (listen(ctx->test_fd, 10) != 0) { - DEBUG(0,("Unable to listen on socket '%s'\n", sock_name)); - goto failed; + if (ctx->services[0] == NULL) { + DEBUG(0, ("No services configured!\n")); + return EINVAL; } - ctx->test_fde = event_add_fd(ev, ctx, ctx->test_fd, - EVENT_FD_READ, test_fd_handler, ctx); + for (i = 0; ctx->services[i]; i++) { - return; + srv = talloc_zero(ctx, struct mt_srv); + if (!srv) { + talloc_free(ctx); + return ENOMEM; + } + srv->name = ctx->services[i]; + srv->mt_ctx = ctx; -failed: - close(ctx->test_fd); -} - -void monitor_task_init(struct task_server *task) -{ - struct mt_ctx *ctx; - - task_server_set_title(task, "sssd[monitor]"); + ret = server_service_init(srv->name, event_ctx, &srv->pid); + if (ret != EOK) { + DEBUG(0,("Failed to restart service '%s'\n", srv->name)); + talloc_free(srv); + } - ctx = talloc_zero(task, struct mt_ctx); - if (!ctx) { - task_server_terminate(task, "fatal error initializing mt_ctx\n"); - return; + set_tasks_checker(srv); } - ctx->task = task; - - /* without an fd event the event system just exits. - * We must always have at least one file base event around - */ - set_test_fd_event(task->event_ctx, ctx); - - /* our test timed event */ - set_test_timed_event(task->event_ctx, ctx); - fprintf(stdout, "test monitor process started!\n"); + return EOK; } |