about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2023-10-08 19:09:47 -0400
committerJune McEnroe <june@causal.agency>2023-10-08 19:09:47 -0400
commit2c2f4cb6a681f427947a27154828f63ce0cecc36 (patch)
tree0fec7925ea1583fee5d4f8fcec0dc9daf2068f4b
parentUse strsignal (diff)
downloadkitd-2c2f4cb6a681f427947a27154828f63ce0cecc36.tar.gz
kitd-2c2f4cb6a681f427947a27154828f63ce0cecc36.zip
Use setitimer(2)
-rw-r--r--kitd.c94
1 files changed, 45 insertions, 49 deletions
diff --git a/kitd.c b/kitd.c
index 91a24ed..2961820 100644
--- a/kitd.c
+++ b/kitd.c
@@ -62,10 +62,10 @@ static void lbFlush(struct LineBuffer *lb, int priority) {
 	memmove(lb->buf, ptr, lb->len);
 }
 
-static const char *humanize(const struct timespec *interval) {
+static const char *humanize(const struct timeval *interval) {
 	static char buf[256];
 	if (!interval->tv_sec) {
-		snprintf(buf, sizeof(buf), "%dms", (int)(interval->tv_nsec / 1000000));
+		snprintf(buf, sizeof(buf), "%dms", (int)(interval->tv_usec / 1000));
 		return buf;
 	}
 	enum { M = 60, H = 60*M, D = 24*H };
@@ -85,10 +85,10 @@ static void signalHandler(int signal) {
 	signals[signal] = 1;
 }
 
-static void parseInterval(struct timespec *interval, const char *millis) {
+static void parseInterval(struct timeval *interval, const char *millis) {
 	unsigned long ms = strtoul(millis, NULL, 10);
 	interval->tv_sec = ms / 1000;
-	interval->tv_nsec = 1000000 * (ms % 1000);
+	interval->tv_usec = 1000 * (ms % 1000);
 }
 
 int main(int argc, char *argv[]) {
@@ -96,8 +96,8 @@ int main(int argc, char *argv[]) {
 
 	bool daemonize = true;
 	const char *name = NULL;
-	struct timespec restart = { .tv_sec = 1 };
-	struct timespec cooloff = { .tv_sec = 15 * 60 };
+	struct timeval restart = { .tv_sec = 1 };
+	struct timeval cooloff = { .tv_sec = 15 * 60 };
 	for (int opt; 0 < (opt = getopt(argc, argv, "c:dn:t:"));) {
 		switch (opt) {
 			break; case 'c': parseInterval(&cooloff, optarg);
@@ -144,6 +144,7 @@ int main(int argc, char *argv[]) {
 
 	signal(SIGHUP, signalHandler);
 	signal(SIGINT, signalHandler);
+	signal(SIGALRM, signalHandler);
 	signal(SIGTERM, signalHandler);
 	signal(SIGCHLD, signalHandler);
 	signal(SIGINFO, signalHandler);
@@ -152,30 +153,37 @@ int main(int argc, char *argv[]) {
 
 	pid_t child = 0;
 	bool stop = false;
-	struct timespec uptime = {0};
-	struct timespec deadline = {0};
-	struct timespec interval = restart;
+	struct timeval uptime = {0};
+	struct timeval interval = restart;
+	signals[SIGALRM] = 1;
 
-	sigset_t mask;
-	sigemptyset(&mask);
 	struct pollfd fds[2] = {
 		{ .fd = stdoutRW[0], .events = POLLIN },
 		{ .fd = stderrRW[0], .events = POLLIN },
 	};
 	for (;;) {
-		struct timespec now;
-		clock_gettime(CLOCK_MONOTONIC, &now);
+		struct timeval now;
+		struct timespec nowspec;
+		clock_gettime(CLOCK_MONOTONIC, &nowspec);
+		TIMESPEC_TO_TIMEVAL(&now, &nowspec);
 
-		if (signals[SIGINFO]) {
-			struct timespec time;
+		if (signals[SIGALRM]) {
+			assert(!child);
+			child = fork();
+			if (child < 0) {
+				syslog(LOG_ERR, "fork: %m");
+				return 1;
+			}
 			if (child) {
-				timespecsub(&now, &uptime, &time);
-				syslog(LOG_INFO, "child %d up %s", child, humanize(&time));
+				uptime = now;
+				signals[SIGALRM] = 0;
 			} else {
-				timespecsub(&deadline, &now, &time);
-				syslog(LOG_INFO, "restarting in %s", humanize(&time));
+				setpgid(0, 0);
+				dup2(stdoutRW[1], STDOUT_FILENO);
+				dup2(stderrRW[1], STDERR_FILENO);
+				execvp(argv[0], (char *const *)argv);
+				err(127, "%s", argv[0]);
 			}
-			signals[SIGINFO] = 0;
 		}
 
 		if (signals[SIGHUP]) {
@@ -228,29 +236,34 @@ int main(int argc, char *argv[]) {
 			}
 
 			if (stop) break;
-			timespecsub(&now, &uptime, &uptime);
-			if (timespeccmp(&uptime, &cooloff, >=)) {
+			timersub(&now, &uptime, &uptime);
+			if (timercmp(&uptime, &cooloff, >=)) {
 				interval = restart;
 			}
 			syslog(LOG_INFO, "restarting in %s", humanize(&interval));
-			timespecadd(&now, &interval, &deadline);
-			timespecadd(&interval, &interval, &interval);
+			struct itimerval timer = { .it_value = interval };
+			setitimer(ITIMER_REAL, &timer, NULL);
+			timeradd(&interval, &interval, &interval);
 		}
 
-		struct timespec timeout;
-		if (!child) {
-			if (timespeccmp(&deadline, &now, <)) {
-				timespecclear(&timeout);
+		if (signals[SIGINFO]) {
+			if (child) {
+				struct timeval time;
+				timersub(&now, &uptime, &time);
+				syslog(LOG_INFO, "child %d up %s", child, humanize(&time));
 			} else {
-				timespecsub(&deadline, &now, &timeout);
+				struct itimerval timer;
+				getitimer(ITIMER_REAL, &timer);
+				syslog(LOG_INFO, "restarting in %s", humanize(&timer.it_value));
 			}
+			signals[SIGINFO] = 0;
 		}
-		int nfds = ppoll(fds, 2, (child ? NULL : &timeout), &mask);
+
+		int nfds = poll(fds, 2, -1);
 		if (nfds < 0 && errno != EINTR) {
-			syslog(LOG_ERR, "ppoll: %m");
+			syslog(LOG_ERR, "poll: %m");
 			continue;
 		}
-
 		if (nfds > 0 && fds[0].revents) {
 			lbFill(&stdoutBuffer, fds[0].fd);
 			lbFlush(&stdoutBuffer, LOG_INFO);
@@ -259,23 +272,6 @@ int main(int argc, char *argv[]) {
 			lbFill(&stderrBuffer, fds[1].fd);
 			lbFlush(&stderrBuffer, LOG_NOTICE);
 		}
-
-		if (!child) {
-			child = fork();
-			if (child < 0) {
-				syslog(LOG_ERR, "fork: %m");
-				return 1;
-			}
-			if (child) {
-				clock_gettime(CLOCK_MONOTONIC, &uptime);
-			} else {
-				setpgid(0, 0);
-				dup2(stdoutRW[1], STDOUT_FILENO);
-				dup2(stderrRW[1], STDERR_FILENO);
-				execvp(argv[0], (char *const *)argv);
-				err(127, "%s", argv[0]);
-			}
-		}
 	}
 
 	lbFill(&stdoutBuffer, fds[0].fd);