summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2022-01-06 22:26:21 +0100
committerLeah Neukirchen <leah@vuxu.org>2022-01-06 22:26:21 +0100
commite86cc66cc9798a506dda02cf39126caff696d456 (patch)
tree96f7281ff4860a36988dc1d8831063e041964e07
parent7438111c1d6e05df06748a9aa43fe9c4cf065131 (diff)
downloadrvnit-e86cc66cc9798a506dda02cf39126caff696d456.tar.gz
rvnit-e86cc66cc9798a506dda02cf39126caff696d456.tar.xz
rvnit-e86cc66cc9798a506dda02cf39126caff696d456.zip
use lock for services access
This makes some continue statements ugly. :(
-rw-r--r--rvnit.c97
1 files changed, 73 insertions, 24 deletions
diff --git a/rvnit.c b/rvnit.c
index 8f7ac73..1c5d352 100644
--- a/rvnit.c
+++ b/rvnit.c
@@ -43,6 +43,8 @@ struct entry {
 };
 
 struct entry services[MAX_SV];
+pthread_mutex_t services_lock;
+
 int level;
 
 pthread_t main_thread;
@@ -225,6 +227,7 @@ socket_loop(void* ignored)
 
 		if (cmd == 's') {
 			time_t now = time(0);
+			pthread_mutex_lock(&services_lock);
 			for (int i = 0; i < MAX_SV; i++) {
 				if (services[i].name[2] == 'D' ||
 				    services[i].name[2] == 'L')
@@ -235,12 +238,14 @@ socket_loop(void* ignored)
 					    services[i].pid > 0 ? (long)(now - services[i].start) : 0,
 					    services[i].status);
 			}
+			pthread_mutex_unlock(&services_lock);
 		}
 
 		if ((cmd == 'd' || cmd == 'u' || charsig(cmd)) && rd > 1) {
 			buf[rd] = 0;
 			printf("got %c|%s|\n", cmd, buf+1);
 
+			pthread_mutex_lock(&services_lock);
 			for (int i = 0; i < MAX_SV; i++) {
 				if (strcmp(services[i].name, buf+1) == 0) {
 					if (cmd == 'd') {
@@ -261,6 +266,7 @@ socket_loop(void* ignored)
 					}
 				}
 			}
+			pthread_mutex_unlock(&services_lock);
 		}
 
 		if (cmd == 'r') {
@@ -302,6 +308,7 @@ logger_loop(void* ignored)
 		fds[nfds].events = POLLIN;
 		nfds++;
 
+		pthread_mutex_lock(&services_lock);
 		for (int i = 0; i < MAX_SV; i++) {
 			if (!services[i].logged && services[i].logfd[0] > 0) {
 				fds[nfds].fd = services[i].logfd[0];
@@ -309,6 +316,7 @@ logger_loop(void* ignored)
 				nfds++;
 			}
 		}
+		pthread_mutex_unlock(&services_lock);
 
 		int n = poll(fds, nfds, -1);
 		if (n < 0) {
@@ -348,6 +356,24 @@ logger_loop(void* ignored)
 				continue;
 			}
 
+			const char *sv = "<unknown>";
+			long pid = -1;
+
+			if (fds[j].fd == selflogfd[0]) {
+				sv = "rvnit";
+				pid = getpid();
+			} else {
+				pthread_mutex_lock(&services_lock);
+				for (int i = 0; i < MAX_SV; i++) {
+					if (services[i].logfd[0] == fds[j].fd) {
+						sv = services[i].name;
+						pid = services[i].display_pid;
+						break;
+					}
+				}
+				pthread_mutex_unlock(&services_lock);
+			}
+
 			char *s = buf;
 			char *e = buf + rd;
 			while (s < e) {
@@ -355,22 +381,6 @@ logger_loop(void* ignored)
 				if (!eol)
 					eol = e;
 
-				const char *sv = "<unknown>";
-				long pid = -1;
-
-				if (fds[j].fd == selflogfd[0]) {
-					sv = "rvnit";
-					pid = getpid();
-				} else {
-					for (int i = 0; i < MAX_SV; i++) {
-						if (services[i].logfd[0] == fds[j].fd) {
-							sv = services[i].name;
-							pid = services[i].display_pid;
-							break;
-						}
-					}
-				}
-
 				printf("%s.%05ld %s[%ld]: %.*s\n",
 				    timestamp, now.tv_nsec / 10000,
 				    sv, pid, (int)(eol - s), s);
@@ -546,6 +556,11 @@ main()
 	fcntl(newlogfd[0], F_SETFD, FD_CLOEXEC);
 	fcntl(newlogfd[1], F_SETFD, FD_CLOEXEC);
 
+	if (pthread_mutex_init(&services_lock, 0) != 0) {
+		perror("pthread_mutex_init");
+		return 111;
+	}
+
 	main_thread = pthread_self();
 
 	/* block all signals in the threads */
@@ -561,7 +576,9 @@ main()
 		return 111;
 	}
 
+	pthread_mutex_lock(&services_lock);
 	rescandir();
+	pthread_mutex_unlock(&services_lock);
 
 	LOG("booting");
 
@@ -570,6 +587,8 @@ main()
 		/* spawn all of level */
 		int oneshot = 0;
 
+		pthread_mutex_lock(&services_lock);
+
 		// spawn loggers first
 		for (i = 0; i < MAX_SV; i++) {
 			if (services[i].level != level)
@@ -598,6 +617,8 @@ main()
 			}
 		}
 
+		pthread_mutex_unlock(&services_lock);
+
 		while (oneshot) {
 			int status = 0;
 			int pid = wait(&status);
@@ -605,12 +626,14 @@ main()
 			if (pid < 0 && errno == ECHILD)
 				break;
 
+			pthread_mutex_lock(&services_lock);
+
 			int i = reap(pid, status);
 			if (i < 0)
-				continue;
+				goto cont1;
 
 			if (services[i].level != level)
-				continue;
+				goto cont1;
 
 			if (services[i].name[2] == 'S') {
 
@@ -620,7 +643,7 @@ main()
 					int r = on_error();
 					if (r == 0) {
 						restart(i);
-						continue;
+						goto cont1;
 					} if (r < 0) {
 						LOG("no error handler, going on");
 					} if (r > 0) {
@@ -634,6 +657,9 @@ main()
 			    services[i].name[2] == 'L') {
 				restart(i);
 			}
+
+cont1:
+			pthread_mutex_unlock(&services_lock);
 		}
 	}
 
@@ -651,12 +677,15 @@ main()
 			break;
 
 		if (want_rescandir) {
+			pthread_mutex_lock(&services_lock);
 			rescandir();
+			pthread_mutex_unlock(&services_lock);
 			want_rescandir = 0;
 		}
 
 		if (want_rescan) {
 			printf("rescanning state\n");
+			pthread_mutex_lock(&services_lock);
 			for (i = 0; i < MAX_SV; i++) {
 				if (services[i].name[2] == 'L') {
 					if (services[i].state == UP &&
@@ -675,6 +704,7 @@ main()
 						kill(services[i].pid, SIGTERM);
 				}
 			}
+			pthread_mutex_unlock(&services_lock);
 
 			want_rescan = 0;
 		}
@@ -690,9 +720,11 @@ main()
 				continue;
 		}
 
+		pthread_mutex_lock(&services_lock);
+
 		int i = reap(pid, status);
 		if (i < 0)
-			continue;
+			goto cont2;
 
 		if (services[i].name[2] == 'D' ||
 		    services[i].name[2] == 'L') {
@@ -702,6 +734,9 @@ main()
 				restart(i);
 			}
 		}
+
+cont2:
+		pthread_mutex_unlock(&services_lock);
 	}
 
 	LOG("shutting down");
@@ -714,6 +749,7 @@ fatal:		; // arrives with level < 99
 		int daemons = 0;
 		int loggers = 0;
 
+		pthread_mutex_lock(&services_lock);
 		for (i = 0; i < MAX_SV; i++) {
 			if (services[i].level != level)
 				continue;
@@ -738,6 +774,7 @@ fatal:		; // arrives with level < 99
 				services[i].state = DOWN;
 			}
 		}
+		pthread_mutex_unlock(&services_lock);
 
 		while (oneshot) {
 			int status = 0;
@@ -746,12 +783,14 @@ fatal:		; // arrives with level < 99
 			if (pid < 0 && errno == ECHILD)
 				break;
 
+			pthread_mutex_lock(&services_lock);
+
 			int i = reap(pid, status);
 			if (i < 0)
-				continue;
+				goto cont3;
 
 			if (services[i].level != level)
-				continue;
+				goto cont3;
 
 			if (services[i].name[2] == 'K') {
 				LOG("oneshot %s exited with status %d", services[i].name, services[i].status);
@@ -765,6 +804,9 @@ fatal:		; // arrives with level < 99
 				LOG("logger %s exited with status %d", services[i].name, services[i].status);
 				loggers--;
 			}
+
+cont3:
+			pthread_mutex_unlock(&services_lock);
 		}
 
 		// only daemons are left, wait up to 7s before sending
@@ -780,6 +822,7 @@ fatal:		; // arrives with level < 99
 				if (slayed)
 					break;
 				LOG("slaying level=%d", level);
+				pthread_mutex_lock(&services_lock);
 				for (i = 0; i < MAX_SV; i++) {
 					if (services[i].level != level)
 						continue;
@@ -788,6 +831,7 @@ fatal:		; // arrives with level < 99
 						kill(services[i].pid, SIGCONT);
 					}
 				}
+				pthread_mutex_unlock(&services_lock);
 				slayed = 1;
 				continue;
 			}
@@ -795,12 +839,14 @@ fatal:		; // arrives with level < 99
 			if (pid < 0 && errno == ECHILD)
 				break;
 
+			pthread_mutex_lock(&services_lock);
+
 			int i = reap(pid, status);
 			if (i < 0)
-				continue;
+				goto cont4;
 
 			if (services[i].level != level)
-				continue;
+				goto cont4;
 
 			if (services[i].name[2] == 'K') {
 				// can't happen
@@ -815,6 +861,9 @@ fatal:		; // arrives with level < 99
 				LOG("logger %s exited with status %d", services[i].name, services[i].status);
 				loggers--;
 			}
+
+cont4:
+			pthread_mutex_unlock(&services_lock);
 		}
 
 		if (daemons) {