summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3b618a3)
raw | patch | inline | side by side (parent: 3b618a3)
author | Pierre-Yves Ritschard <pyr@spootnik.org> | |
Fri, 7 Nov 2014 12:56:21 +0000 (13:56 +0100) | ||
committer | Pierre-Yves Ritschard <pyr@spootnik.org> | |
Tue, 11 Nov 2014 09:24:26 +0000 (10:24 +0100) |
This checks appropriate environment variables. When supervised
by either upstart or systemd, collectd will not daemonize but
will signal readyness with the appropriate method.
This allows collectd to be either configured with `expect stop`
in upstart or `Type=notify` with systemd.
The rationale for this is detailed here: http://spootnik.org/entries/2014/11/09_pid-tracking-in-modern-init-systems.html
by either upstart or systemd, collectd will not daemonize but
will signal readyness with the appropriate method.
This allows collectd to be either configured with `expect stop`
in upstart or `Type=notify` with systemd.
The rationale for this is detailed here: http://spootnik.org/entries/2014/11/09_pid-tracking-in-modern-init-systems.html
src/daemon/collectd.c | patch | blob | history |
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
index 2e2d821aade194873c923ceabcf8951291d0dc69..eb5404f8fda21a148d3a6091fbd67814d63fd733 100644 (file)
--- a/src/daemon/collectd.c
+++ b/src/daemon/collectd.c
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netdb.h>
#include <pthread.h>
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
-
+
dirlen = strlen (dir);
while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
dir[--dirlen] = '\0';
static void exit_usage (int status)
{
printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
-
+
"Available options:\n"
" General:\n"
" -C <file> Configuration file.\n"
} /* static int pidfile_remove (const char *file) */
#endif /* COLLECT_DAEMON */
+int notify_upstart (void)
+{
+ const char *upstart_job = getenv("UPSTART_JOB");
+
+ if (upstart_job == NULL)
+ return 0;
+
+ if (strcmp(upstart_job, "collectd") != 0)
+ return 0;
+
+ WARNING ("supervised by upstart, will stop to signal readyness");
+ raise(SIGSTOP);
+ unsetenv("UPSTART_JOB");
+
+ return 1;
+}
+
+int notify_systemd (void)
+{
+ int fd = -1;
+ const char *notifysocket = getenv("NOTIFY_SOCKET");
+ struct sockaddr_un su;
+ struct iovec iov;
+ struct msghdr hdr;
+
+ if (notifysocket == NULL)
+ return 0;
+
+ if ((strchr("@/", notifysocket[0])) == NULL ||
+ strlen(notifysocket) < 2)
+ return 0;
+
+ WARNING ("supervised by systemd, will signal readyness");
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ WARNING ("cannot contact systemd socket %s", notifysocket);
+ return 0;
+ }
+
+ bzero(&su, sizeof(su));
+ su.sun_family = AF_UNIX;
+ sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
+
+ if (notifysocket[0] == '@')
+ su.sun_path[0] = 0;
+
+ bzero(&iov, sizeof(iov));
+ iov.iov_base = "READY=1";
+ iov.iov_len = strlen("READY=1");
+
+ bzero(&hdr, sizeof(hdr));
+ hdr.msg_name = &su;
+ hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
+ strlen(notifysocket);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ unsetenv("NOTIFY_SOCKET");
+ if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
+ WARNING ("cannot send notification to systemd");
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ return 1;
+}
+
int main (int argc, char **argv)
{
struct sigaction sig_int_action;
sig_chld_action.sa_handler = SIG_IGN;
sigaction (SIGCHLD, &sig_chld_action, NULL);
- if (daemonize)
+ /*
+ * Only daemonize if we're not being supervised
+ * by upstart or systemd.
+ */
+ if (daemonize && notify_upstart() == 0 && notify_systemd() == 0)
{
if ((pid = fork ()) == -1)
{