diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/afb-supervision.c | 31 | ||||
-rw-r--r-- | src/afs-discover.c | 66 | ||||
-rw-r--r-- | src/afs-supervisor.c | 39 |
4 files changed, 125 insertions, 13 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 353db3b6..89a181f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,7 +85,7 @@ INSTALL(TARGETS afb-daemon ########################################### # build and install afb-daemon ########################################### -ADD_EXECUTABLE(afs-supervisor afs-supervisor.c) +ADD_EXECUTABLE(afs-supervisor afs-supervisor.c afs-discover.c) TARGET_LINK_LIBRARIES(afs-supervisor afb-lib ${link_libraries} diff --git a/src/afb-supervision.c b/src/afb-supervision.c index ecdcbf20..f41ca18b 100644 --- a/src/afb-supervision.c +++ b/src/afb-supervision.c @@ -45,6 +45,7 @@ #include "afb-debug.h" #include "verbose.h" #include "wrap-json.h" +#include "jobs.h" extern struct afb_config *main_config; @@ -111,20 +112,24 @@ static int open_supervisor_socket(const char *path) return fd; } -static void cleanup_supervisor(void *nada) +static void disconnect_supervisor() { - struct afb_trace *t = __atomic_exchange_n(&trace, NULL, __ATOMIC_RELAXED); + struct afb_stub_ws *s; + struct afb_trace *t; + + INFO("Disconnecting supervision"); + s = __atomic_exchange_n(&supervisor, NULL, __ATOMIC_RELAXED); + t = __atomic_exchange_n(&trace, NULL, __ATOMIC_RELAXED); + if (s) + afb_stub_ws_unref(s); if (t) afb_trace_unref(t); - supervisor = NULL; } -static void disconnect_supervisor() +static void on_supervisor_hangup(struct afb_stub_ws *s) { - struct afb_stub_ws *s = __atomic_exchange_n(&supervisor, NULL, __ATOMIC_RELAXED); - - if (s) - afb_stub_ws_unref(s); + if (s && s == supervisor) + disconnect_supervisor(); } /* try to connect to supervisor */ @@ -195,6 +200,7 @@ static void try_connect_supervisor() ERROR("Creation of supervisor failed: %m"); goto end2; } + afb_stub_ws_on_hangup(supervisor, on_supervisor_hangup); /* successful termination */ goto end; @@ -205,11 +211,18 @@ end: pthread_mutex_unlock(&mutex); } -static void on_sighup(int signum) +static void try_connect_supervisor_job(int signum, void *args) { + INFO("Try to connect supervisor after SIGHUP"); try_connect_supervisor(); } +static void on_sighup(int signum) +{ + INFO("Supervision received a SIGHUP"); + jobs_queue(NULL, 0, try_connect_supervisor_job, NULL); +} + /** * initalize the supervision */ diff --git a/src/afs-discover.c b/src/afs-discover.c new file mode 100644 index 00000000..cad95574 --- /dev/null +++ b/src/afs-discover.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <ctype.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> + +void afs_discover(const char *pattern, void (*callback)(void *closure, pid_t pid), void *closure) +{ + intmax_t n; + DIR *dir; + struct dirent *ent; + char *name; + char exe[PATH_MAX], lnk[PATH_MAX]; + + dir = opendir("/proc"); + while ((ent = readdir(dir))) { + name = ent->d_name; + while (isdigit(*name)) + name++; + if (*name) + continue; + n = snprintf(exe, sizeof exe, "/proc/%s/exe", ent->d_name); + if (n < 0 || (size_t)n >= sizeof exe) + continue; + n = readlink(exe, lnk, sizeof lnk); + if (n < 0 || (size_t)n >= sizeof lnk) + continue; + lnk[n] = 0; + name = lnk; + while(*name) { + while(*name == '/') + name++; + if (*name) { + if (!strcmp(name, pattern)) { + callback(closure, (pid_t)atoi(ent->d_name)); + break; + } + while(*++name && *name != '/'); + } + } + } + closedir(dir); +} + diff --git a/src/afs-supervisor.c b/src/afs-supervisor.c index 8d76832a..8cf21cb5 100644 --- a/src/afs-supervisor.c +++ b/src/afs-supervisor.c @@ -49,6 +49,8 @@ #include "verbose.h" #include "wrap-json.h" +extern void afs_discover(const char *pattern, void (*callback)(void *closure, pid_t pid), void *closure); + /* supervised items */ struct supervised { @@ -210,6 +212,22 @@ static int make_supervised(int fd, struct afb_cred *cred) return 0; } +/** + * Search the supervised of 'pid', return it or NULL. + */ +static struct supervised *supervised_of_pid(pid_t pid) +{ + struct supervised *s; + + pthread_mutex_lock(&mutex); + s = superviseds; + while (s && pid != s->cred->pid) + s = s->next; + pthread_mutex_unlock(&mutex); + + return s; +} + /* * handles incoming connection on 'sock' */ @@ -252,6 +270,21 @@ static int listening(sd_event_source *src, int fd, uint32_t revents, void *closu return 0; } +/* + */ +static void discovered_cb(void *closure, pid_t pid) +{ + struct supervised *s; + + s = supervised_of_pid(pid); + if (!s) + kill(pid, SIGHUP); +} + +static void discover_supervised() +{ + afs_discover("afb-daemon", discovered_cb, NULL); +} /** * initalize the supervision @@ -333,6 +366,8 @@ static void start(int signum, void *arg) exit(1); sd_notify(1, "READY=1"); + + discover_supervised(); } /** @@ -396,9 +431,7 @@ static void propagate(struct afb_req req, const char *verb) afb_xreq_fail(xreq, "bad-pid", NULL); return; } - s = superviseds; - while (s && p != (int)s->cred->pid) - s = s->next; + s = supervised_of_pid((pid_t)p); if (!s) { afb_req_fail(req, "unknown-pid", NULL); return; |