summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2022-01-06 22:23:18 +0100
committerLeah Neukirchen <leah@vuxu.org>2022-01-06 22:23:18 +0100
commit7438111c1d6e05df06748a9aa43fe9c4cf065131 (patch)
treedb5aab33154a1423348c4544f728b9216b68b3fd
parent5cef60e29c23554a02efc061dca0812b8a08a1e9 (diff)
downloadrvnit-7438111c1d6e05df06748a9aa43fe9c4cf065131.tar.gz
rvnit-7438111c1d6e05df06748a9aa43fe9c4cf065131.tar.xz
rvnit-7438111c1d6e05df06748a9aa43fe9c4cf065131.zip
extract rescandir
-rw-r--r--rvnit.c129
1 files changed, 88 insertions, 41 deletions
diff --git a/rvnit.c b/rvnit.c
index 7e03bc6..8f7ac73 100644
--- a/rvnit.c
+++ b/rvnit.c
@@ -39,6 +39,7 @@ struct entry {
 	time_t start;
 	int status;
 	char state;
+	char seen;
 };
 
 struct entry services[MAX_SV];
@@ -53,8 +54,8 @@ int newlogfd[2];
 
 sig_atomic_t want_shutdown;
 sig_atomic_t want_rescan;
-
-int want_reboot = 0;
+sig_atomic_t want_rescandir;
+sig_atomic_t want_reboot;
 
 void
 on_sigint(int sig)
@@ -85,6 +86,8 @@ restart(int i)
 
 	int loggerpipe[2] = { -1, -1 };
 
+	LOG("start %s\n", services[i].name);
+
 	if (services[i].logfd[0] == -1) {
 		pipe(services[i].logfd);
 		fcntl(services[i].logfd[0], F_SETFL, O_NONBLOCK);
@@ -260,6 +263,12 @@ socket_loop(void* ignored)
 			}
 		}
 
+		if (cmd == 'r') {
+			want_rescandir = 1;
+			want_rescan = 1;
+			pthread_kill(main_thread, SIGCONT);
+		}
+
 		if (cmd == 'X') {
 			want_shutdown = 1;
 			pthread_kill(main_thread, SIGCONT);
@@ -429,15 +438,6 @@ timedwait(int *wstatus, int secs)
 	return pid;
 }
 
-int
-svcmp(void const *a, void const *b)
-{
-	const struct entry *sv_a = a;
-	const struct entry *sv_b = b;
-
-	return strcmp(sv_a->name, sv_b->name);
-}
-
 /* -1: no error handler, 0: error handler successful, 1: error handler failed */
 int
 on_error()
@@ -470,41 +470,26 @@ found:
 }
 
 int
-main()
+svcmp(void const *a, void const *b)
 {
-	pipe(selflogfd);
-	fcntl(selflogfd[0], F_SETFL, O_NONBLOCK);
-	fcntl(selflogfd[1], F_SETFL, O_NONBLOCK);
-	fcntl(selflogfd[0], F_SETFD, FD_CLOEXEC);
-	fcntl(selflogfd[1], F_SETFD, FD_CLOEXEC);
-
-	pipe(newlogfd);
-	fcntl(newlogfd[0], F_SETFL, O_NONBLOCK);
-	fcntl(newlogfd[1], F_SETFL, O_NONBLOCK);
-	fcntl(newlogfd[0], F_SETFD, FD_CLOEXEC);
-	fcntl(newlogfd[1], F_SETFD, FD_CLOEXEC);
-
-	main_thread = pthread_self();
-
-	/* block all signals in the threads */
-	sigset_t allset;
-	sigfillset(&allset);
-	sigprocmask(SIG_BLOCK, &allset, 0);
-	pthread_create(&socket_thread, 0, socket_loop, 0);
-	pthread_create(&logger_thread, 0, logger_loop, 0);
-	sigprocmask(SIG_UNBLOCK, &allset, 0);
+	const struct entry *sv_a = a;
+	const struct entry *sv_b = b;
 
-	if (chdir("sv") < 0) {
-		perror("chdir");
-		return 111;
-	}
+	return strcmp(sv_a->name, sv_b->name);
+}
 
+void
+rescandir()
+{
 	DIR *dir = opendir(".");
 	if (!dir)
-		return 111;
+		abort();
 
 	int i = 0;
 
+	for (int j = 0; j < MAX_SV; j++)
+		services[j].seen = 0;
+
 	struct dirent *ent;
 	while ((ent = readdir(dir))) {
 		if (!isdigit(ent->d_name[0]) || !isdigit(ent->d_name[1]))
@@ -513,6 +498,16 @@ main()
 		if (ent->d_name[strlen(ent->d_name) - 1] == '~')
 			continue;
 
+		while (services[i].state != UNDEF)
+			i++;
+		for (int j = 0; j < MAX_SV; j++)
+			if (strcmp(services[j].name, ent->d_name) == 0) {
+				services[j].seen = 1;
+				goto next;  /* already know this one */
+			}
+
+		services[i].seen = 1;
+
 		services[i].level = 10 * (ent->d_name[0] - '0') +
 		    (ent->d_name[1] - '0');
 		snprintf(services[i].name, sizeof services[i].name,
@@ -523,14 +518,54 @@ main()
 		services[i].logfd[1] = -1;
 		services[i].logged = 0;
 		i++;
+
+next:		;
 	}
 
-	closedir(dir);
+	for (int j = 0; j < MAX_SV; j++)
+		if (services[j].state != UNDEF && services[j].seen == 0)
+			services[j].state = DOWN;
 
 	qsort(services, MAX_SV, sizeof services[0], svcmp);
 
+	closedir(dir);
+}
+
+int
+main()
+{
+	pipe(selflogfd);
+	fcntl(selflogfd[0], F_SETFL, O_NONBLOCK);
+	fcntl(selflogfd[1], F_SETFL, O_NONBLOCK);
+	fcntl(selflogfd[0], F_SETFD, FD_CLOEXEC);
+	fcntl(selflogfd[1], F_SETFD, FD_CLOEXEC);
+
+	pipe(newlogfd);
+	fcntl(newlogfd[0], F_SETFL, O_NONBLOCK);
+	fcntl(newlogfd[1], F_SETFL, O_NONBLOCK);
+	fcntl(newlogfd[0], F_SETFD, FD_CLOEXEC);
+	fcntl(newlogfd[1], F_SETFD, FD_CLOEXEC);
+
+	main_thread = pthread_self();
+
+	/* block all signals in the threads */
+	sigset_t allset;
+	sigfillset(&allset);
+	sigprocmask(SIG_BLOCK, &allset, 0);
+	pthread_create(&socket_thread, 0, socket_loop, 0);
+	pthread_create(&logger_thread, 0, logger_loop, 0);
+	sigprocmask(SIG_UNBLOCK, &allset, 0);
+
+	if (chdir("sv") < 0) {
+		perror("chdir");
+		return 111;
+	}
+
+	rescandir();
+
 	LOG("booting");
 
+	int i;
 	for (level = 0; level < 100; level++) {
 		/* spawn all of level */
 		int oneshot = 0;
@@ -615,11 +650,23 @@ main()
 		if (want_shutdown)
 			break;
 
+		if (want_rescandir) {
+			rescandir();
+			want_rescandir = 0;
+		}
+
 		if (want_rescan) {
 			printf("rescanning state\n");
 			for (i = 0; i < MAX_SV; i++) {
-				if (services[i].name[2] == 'D' ||
-				    services[i].name[2] == 'L') {
+				if (services[i].name[2] == 'L') {
+					if (services[i].state == UP &&
+					    services[i].pid == 0)
+						restart(i);
+					if (services[i].state == DOWN &&
+					    services[i].pid > 0)
+						kill(services[i].pid, SIGTERM);
+				}
+				if (services[i].name[2] == 'D') {
 					if (services[i].state == UP &&
 					    services[i].pid == 0)
 						restart(i);