aboutsummaryrefslogtreecommitdiffstats
path: root/scan.c
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2015-11-27 00:30:30 +0100
committerMarius Halden <marius.h@lden.org>2015-11-27 00:30:30 +0100
commitd9396554d23c1714d3ac7163265fe506827530c8 (patch)
tree37b6d39351ac172e0d4c5986043c5e51edd2564d /scan.c
parentcf04e4f8e98df62a361bcddfdd56e0a661f4e7b0 (diff)
downloadsvcmon-d9396554d23c1714d3ac7163265fe506827530c8.tar.gz
svcmon-d9396554d23c1714d3ac7163265fe506827530c8.tar.bz2
svcmon-d9396554d23c1714d3ac7163265fe506827530c8.tar.xz
Do some locking on startup, signal existing supervisors.
Diffstat (limited to 'scan.c')
-rw-r--r--scan.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/scan.c b/scan.c
index f9a6b05..ee3b118 100644
--- a/scan.c
+++ b/scan.c
@@ -9,12 +9,18 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/event.h>
+#include <sys/file.h>
#include <sys/procctl.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
+/*
+ * TODO:
+ * - Don't start procs instantly after they die, wait some seconds first.
+ */
+
const char supdir[] = "/home/marius/r/svc";
char *super_path[] = { "/home/marius/r/supervise", NULL, NULL };
@@ -279,12 +285,104 @@ try_wait()
}
int
+acquire_lock()
+{
+ int lock_fd;
+ char *lock_path;
+
+ if (asprintf(&lock_path, "%s/lock", supdir) == -1 || lock_path == NULL)
+ err(1, "asprintf()");
+
+ if ((lock_fd = open(lock_path, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644)) == -1)
+ err(1, "open()");
+
+ if (flock(lock_fd, LOCK_EX | LOCK_NB) == -1) {
+ if (errno == EWOULDBLOCK) {
+ fprintf(stderr, "%s is locked\n", lock_path);
+ exit(1);
+ } else {
+ err(1, "flock()");
+ }
+ }
+
+ free(lock_path);
+
+ return lock_fd;
+}
+
+void
+signal_existing(int dir_fd)
+{
+ DIR *dir;
+ struct dirent *dp;
+ char *ctrl_path, *lock_path;
+ int ctrl_fd, lock_fd;
+ sigmask_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGPIPE);
+
+ dir = fdopendir(dir_fd);
+
+ while ((dp = readdir(dir)) != NULL) {
+ if (dp->d_type != DT_DIR)
+ continue;
+ if (dp->d_name[0] == '.')
+ continue;
+
+ if (asprintf(&ctrl_path, "%s/supervise/control", dp->d_name) == -1 || ctrl_path == NULL)
+ err(1, "asprintf()");
+ if (asprintf(&lock_path, "%s/supervise/lock", dp->d_name) == -1 || lock_path == NULL)
+ err(1, "asprintf()");
+
+ if ((lock_fd = open(lock_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)) == -1)
+ err(1, "open()");
+
+ if (flock(lock_fd, LOCK_EX | LOCK_NB) == -1) {
+ if (errno == EWOULDBLOCK) {
+ if ((ctrl_fd = open(ctrl_path, O_WRONLY | O_CLOEXEC)) == -1)
+ err(1, "open()");
+
+ if (setprocmask(SIG_BLOCK, &mask, NULL) == -1)
+ err(1, "setprocmask()");
+
+ if (write(ctrl_fd, "x", 1) != 1) {
+ if (errno != EPIPE)
+ err(1, "write()");
+ }
+
+ if (setprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
+ err(1, "setprocmask()");
+
+ if (close(ctrl_fd) == -1)
+ err(1, "close()");
+ } else {
+ err(1, "flock()");
+ }
+ }
+
+ if (close(lock_fd) == -1)
+ err(1, "flock()");
+
+ free(lock_path);
+ free(ctrl_path);
+ }
+
+ rewinddir(dir);
+
+ if (fdclosedir(dir) == -1)
+ err(1, "fdclosedir()");
+}
+
+int
main(int argc, char **argv)
{
- int kq, dir_fd;
+ int kq, dir_fd, lock_fd;
struct kevent evt;
pid_t mypid = getpid();
+ lock_fd = acquire_lock();
+
if (procctl(P_PID, mypid, PROC_REAP_ACQUIRE, NULL) == -1)
err(1, "procctl()");
@@ -323,6 +421,8 @@ main(int argc, char **argv)
perror("close()");
if (close(dir_fd) == -1)
perror("close()");
+ if (close(lock_fd) == -1)
+ perror("close()");
reset_signals(); /* Make SIGTERM/INT work again in case reap_all uses a long time. */