summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2018-02-14 15:12:30 +0100
committerJosé Bollo <jose.bollo@iot.bzh>2018-02-14 15:12:30 +0100
commitabbb4599f0b921c6f434b6bd02bcfb277eecf745 (patch)
treefd8a7449742fbb4c445286529349ab12cca9540a
parent4788fcd7becaef5a665dea0f9c0345401c80f757 (diff)
afs-supervisor: Add discovery mechanic
Change-Id: Icfcdcc16d0433454c9bb0785d0690f7f173980ae Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/afb-supervision.c31
-rw-r--r--src/afs-discover.c66
-rw-r--r--src/afs-supervisor.c39
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;