afs-supervisor: Add discovery mechanic
authorJosé Bollo <jose.bollo@iot.bzh>
Wed, 14 Feb 2018 14:12:30 +0000 (15:12 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Wed, 14 Feb 2018 14:12:30 +0000 (15:12 +0100)
Change-Id: Icfcdcc16d0433454c9bb0785d0690f7f173980ae
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/CMakeLists.txt
src/afb-supervision.c
src/afs-discover.c [new file with mode: 0644]
src/afs-supervisor.c

index 353db3b..89a181f 100644 (file)
@@ -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}
index ecdcbf2..f41ca18 100644 (file)
@@ -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 (file)
index 0000000..cad9557
--- /dev/null
@@ -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);
+}
+
index 8d76832..8cf21cb 100644 (file)
@@ -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;