diff options
author | Leah Neukirchen <leah@vuxu.org> | 2023-12-23 19:11:07 +0100 |
---|---|---|
committer | Leah Neukirchen <leah@vuxu.org> | 2023-12-23 19:11:07 +0100 |
commit | 5230dd78c4882e4b9d17aab9cc026718c89b7721 (patch) | |
tree | 2585b91588909ac22619eabcac34239b4da0c5b9 | |
parent | e12a7cdb754e5564f931fa440b2e311b4aa939ce (diff) | |
download | nitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.tar.gz nitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.tar.xz nitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.zip |
add a notification mechanism
To notify, send a datagram message to all unix sockets in a notification directory that start with the service name (or ALL) followed by a comma. (Works a bit like s6-ftrig but has constant memory and fd usage.)
-rw-r--r-- | nitro.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/nitro.c b/nitro.c index 809c18f..bf14420 100644 --- a/nitro.c +++ b/nitro.c @@ -92,6 +92,8 @@ int selfpipe[2]; int globallog[2]; int globaloutfd = 2; DIR *cwd; +DIR *notifydir; +char notifypath[256]; char logbuf[4096]; char *logbufend = logbuf; @@ -134,6 +136,7 @@ stat_slash(const char *dir, const char *name, struct stat *st) } void process_step(int i, enum process_events ev); +void notify(int); void proc_launch(int i) @@ -357,6 +360,8 @@ proc_cleanup(int i) if (services[i].logpipe[1] > 0) close(services[i].logpipe[1]); } + + notify(i); } void @@ -527,6 +532,7 @@ process_step(int i, enum process_events ev) case PROC_FATAL: proc_cleanup(i); services[i].state = PROC_FATAL; + notify(i); break; case PROC_SETUP: /* can't happen */ @@ -548,6 +554,7 @@ process_step(int i, enum process_events ev) case PROC_STARTING: services[i].state = PROC_UP; + notify(i); break; case PROC_RESTART: @@ -736,6 +743,12 @@ open_control_socket() { dir[last_slash - path] = 0; mkdir(dir, 0700); // ignore errors + + strcpy(notifypath, dir); + strcat(notifypath, "/notify/"); + mkdir(notifypath, 0700); + // ignore errors + notifydir = opendir(notifypath); } struct sockaddr_un addr = { 0 }; @@ -759,6 +772,46 @@ open_control_socket() { } } +void +notify(int i) +{ + printf("NOTIFY\n"); + + if (!notifydir) + return; + + char notifybuf[128]; + sprintf(notifybuf, "%c%s\n", 64 + services[i].state, + services[i].name); + + struct dirent *ent; + rewinddir(notifydir); + while ((ent = readdir(notifydir))) { + char *name = ent->d_name; + + if (name[0] == '.') + continue; + + printf("notify check %s\n", name); + + if ((strncmp(name, services[i].name, strlen(services[i].name)) == 0 && + name[strlen(services[i].name)] == ',') || + (strncmp("ALL,", name, 4) == 0)) { + + struct sockaddr_un addr = { 0 }; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, notifypath, sizeof addr.sun_path - 1); + strcat(addr.sun_path, name); + + printf("notify to %s\n", addr.sun_path); + + sendto(controlsock, notifybuf, strlen(notifybuf), + MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof addr); + } + } + +} + int charsig(char c) { |