about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-08-15 18:25:40 -0400
committerJune McEnroe <june@causal.agency>2020-08-15 18:25:40 -0400
commit497cafbf0f2e96c21539fcc65b149450de262be8 (patch)
treeb464fc74478038c30562afc5f5cea9721c762aea
parentLog when service name pattern doesn't match (diff)
downloadcatsit-497cafbf0f2e96c21539fcc65b149450de262be8.tar.gz
catsit-497cafbf0f2e96c21539fcc65b149450de262be8.zip
Add reset interval after which restart interval is reset
-rw-r--r--catsitd.816
-rw-r--r--daemon.c14
-rw-r--r--daemon.h2
-rw-r--r--service.c10
4 files changed, 30 insertions, 12 deletions
diff --git a/catsitd.8 b/catsitd.8
index cdb77a0..dcc4a38 100644
--- a/catsitd.8
+++ b/catsitd.8
@@ -1,4 +1,4 @@
-.Dd August 13, 2020
+.Dd August 15, 2020
 .Dt CATSITD 8
 .Os
 .
@@ -14,8 +14,9 @@
 .Op Fl f Ar config
 .Op Fl g Ar group
 .Op Fl p Ar pidfile
+.Op Fl r Ar reset
 .Op Fl s Ar stopexits
-.Op Fl t Ar interval
+.Op Fl t Ar restart
 .Op Fl u Ar user
 .
 .Sh DESCRIPTION
@@ -100,6 +101,13 @@ Write the PID of the
 process to
 .Ar pidfile .
 .
+.It Fl r Ar reset
+Set the interval in milliseconds
+for which a process must live
+to have its service restart interval
+reset to the initial value.
+The default interval is 15 minutes.
+.
 .It Fl s Ar stopexits
 Set the list of exit statuses
 for which a restart will not be attempted.
@@ -118,10 +126,10 @@ defined in
 The exit status 127
 is always treated as a stop exit.
 .
-.It Fl t Ar interval
+.It Fl t Ar restart
 Set the initial interval between restarts
 in milliseconds.
-The default interval is 1000.
+The default interval is 1 second.
 .
 .It Fl u Ar user
 Change user to
diff --git a/daemon.c b/daemon.c
index 3cfe24f..2e58c82 100644
--- a/daemon.c
+++ b/daemon.c
@@ -48,8 +48,9 @@
 
 #define WS " \t"
 
-struct timespec restartInterval = { .tv_sec = 1 };
 struct Set256 stopExits;
+struct timespec restartInterval = { .tv_sec = 1 };
+struct timespec resetInterval = { .tv_sec = 15 * 60 };
 
 static volatile sig_atomic_t signals[NSIG];
 static void signalHandler(int signal) {
@@ -176,10 +177,10 @@ static void parseExits(char *list) {
 	}
 }
 
-static void parseInterval(const char *millis) {
+static void parseInterval(struct timespec *interval, const char *millis) {
 	unsigned long ms = strtoul(millis, NULL, 10);
-	restartInterval.tv_sec = ms / 1000;
-	restartInterval.tv_nsec = 1000000 * (ms % 1000);
+	interval->tv_sec = ms / 1000;
+	interval->tv_nsec = 1000000 * (ms % 1000);
 }
 
 static void setTitle(void) {
@@ -208,7 +209,7 @@ int main(int argc, char *argv[]) {
 	const char *userName = NULL;
 	const char *groupName = NULL;
 
-	for (int opt; 0 < (opt = getopt(argc, argv, "C:c:df:g:p:s:t:u:"));) {
+	for (int opt; 0 < (opt = getopt(argc, argv, "C:c:df:g:p:r:s:t:u:"));) {
 		switch (opt) {
 			break; case 'C': serviceDir = optarg;
 			break; case 'c': fifoPath = optarg;
@@ -216,8 +217,9 @@ int main(int argc, char *argv[]) {
 			break; case 'f': configPath = optarg;
 			break; case 'g': groupName = optarg;
 			break; case 'p': pidPath = optarg;
+			break; case 'r': parseInterval(&resetInterval, optarg);
 			break; case 's': parseExits(optarg);
-			break; case 't': parseInterval(optarg);
+			break; case 't': parseInterval(&restartInterval, optarg);
 			break; case 'u': userName = optarg;
 			break; default:  return EX_USAGE;
 		}
diff --git a/daemon.h b/daemon.h
index b8bcb9b..1ee3ea5 100644
--- a/daemon.h
+++ b/daemon.h
@@ -119,6 +119,7 @@ struct Service {
 	int errPipe[2];
 	struct Line outLine;
 	struct Line errLine;
+	struct timespec startTime;
 	struct timespec restartInterval;
 	struct timespec restartDeadline;
 };
@@ -156,3 +157,4 @@ static inline uint32_t setTest(const struct Set256 *set, byte x) {
 enum { StopExit = 127 };
 extern struct Set256 stopExits;
 extern struct timespec restartInterval;
+extern struct timespec resetInterval;
diff --git a/service.c b/service.c
index 3246fef..fef9b00 100644
--- a/service.c
+++ b/service.c
@@ -163,8 +163,9 @@ void serviceStart(struct Service *service) {
 		return;
 	}
 	if (service->pid) {
-		syslog(LOG_NOTICE, "%s[%d] started", service->name, service->pid);
 		service->state = Start;
+		clock_gettime(CLOCK_MONOTONIC, &service->startTime);
+		syslog(LOG_NOTICE, "%s[%d] started", service->name, service->pid);
 		return;
 	}
 
@@ -282,7 +283,12 @@ void serviceReap(pid_t pid, int status) {
 	}
 
 	if (service->intent == Start) {
-		// TODO: Determine if restart interval should be reset?
+		struct timespec uptime;
+		clock_gettime(CLOCK_MONOTONIC, &uptime);
+		timespecsub(&uptime, &service->startTime, &uptime);
+		if (timespeccmp(&uptime, &resetInterval, >=)) {
+			service->restartInterval = restartInterval;
+		}
 		setDeadline(service);
 		syslog(
 			LOG_NOTICE, "%s[%d] restarting in %lds",