From f731537024c367368b728ed01c9232c3b1951589 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <goliath@infraroot.at>
Date: Wed, 13 May 2020 18:17:53 +0200
Subject: initd: merge "handle exited" into "wait for a child process"

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
---
 initd/main.c | 134 ++++++++++++++++++++++++++---------------------------------
 1 file changed, 59 insertions(+), 75 deletions(-)

diff --git a/initd/main.c b/initd/main.c
index 332722c..dc2e631 100644
--- a/initd/main.c
+++ b/initd/main.c
@@ -54,63 +54,6 @@ fail:
 	return;
 }
 
-static void check_target_completion(void)
-{
-	if (singleshot > 0 || queue_idx < queue_count[target])
-		return;
-
-	switch (target) {
-	case TGT_BOOT:
-		break;
-	case TGT_SHUTDOWN:
-		for (;;)
-			reboot(RB_POWER_OFF);
-		break;
-	case TGT_REBOOT:
-		for (;;)
-			reboot(RB_AUTOBOOT);
-		break;
-	}
-}
-
-static void supervisor_handle_exited(pid_t pid, int status)
-{
-	svc_run_data_t *rt;
-	service_t *svc;
-	size_t i;
-
-	for (i = 0; i < rt_count; ++i) {
-		if (rt_data[i].pid == pid)
-			break;
-	}
-
-	if (i >= rt_count)
-		return;
-
-	rt = rt_data + i;
-	svc = rt->svc;
-	rt->status = status;
-	rt->pid = -1;
-
-	if (svc->type == SVC_RESPAWN) {
-		if (target != TGT_REBOOT && target != TGT_SHUTDOWN)
-			respawn(rt);
-	} else {
-		if (rt->status == EXIT_SUCCESS) {
-			rt->state = STATE_COMPLETED;
-		} else {
-			rt->state = STATE_FAILED;
-		}
-
-		print_status(svc->desc, rt->state);
-
-		if (svc->type == SVC_ONCE)
-			singleshot -= 1;
-
-		check_target_completion();
-	}
-}
-
 static void supervisor_init(void)
 {
 	int status = STATE_FAILED;
@@ -159,16 +102,43 @@ out:
 	print_status("reading configuration from " SVCDIR, status);
 }
 
-static pid_t wait_for_process(int *status)
+static svc_run_data_t *wait_for_process(void)
 {
-	pid_t pid = wait(status);
+	svc_run_data_t *rt;
+	int status;
+	pid_t pid;
+	size_t i;
+
+	do {
+		pid = wait(&status);
+		if (pid == -1)
+			return NULL;
 
-	if (pid == -1 || !WIFEXITED(*status)) {
-		*status = EXIT_FAILURE;
+		for (i = 0; i < rt_count && rt_data[i].pid != pid; ++i)
+			;
+	} while (i >= rt_count);
+
+	rt = rt_data + i;
+	rt->status = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
+	rt->pid = -1;
+
+	if (rt->svc->type == SVC_RESPAWN) {
+		if (target != TGT_REBOOT && target != TGT_SHUTDOWN)
+			respawn(rt);
 	} else {
-		*status = WEXITSTATUS(*status);
+		if (rt->status == EXIT_SUCCESS) {
+			rt->state = STATE_COMPLETED;
+		} else {
+			rt->state = STATE_FAILED;
+		}
+
+		print_status(rt->svc->desc, rt->state);
+
+		if (rt->svc->type == SVC_ONCE)
+			singleshot -= 1;
 	}
-	return pid;
+
+	return rt;
 }
 
 static void handle_signal(int signo)
@@ -193,14 +163,31 @@ static void handle_signal(int signo)
 	}
 }
 
+static void check_target_completion(void)
+{
+	if (singleshot > 0 || queue_idx < queue_count[target])
+		return;
+
+	switch (target) {
+	case TGT_BOOT:
+		break;
+	case TGT_SHUTDOWN:
+		for (;;)
+			reboot(RB_POWER_OFF);
+		break;
+	case TGT_REBOOT:
+		for (;;)
+			reboot(RB_AUTOBOOT);
+		break;
+	}
+}
+
 int main(void)
 {
+	svc_run_data_t *rt, *terminated;
 	struct sigaction act;
-	svc_run_data_t *rt;
 	service_t *svc;
 	size_t count;
-	int status;
-	pid_t pid;
 
 	supervisor_init();
 
@@ -219,8 +206,10 @@ int main(void)
 		count = queue_count[target];
 
 		if (queue_idx >= count) {
-			pid = wait_for_process(&status);
-			supervisor_handle_exited(pid, status);
+			terminated = wait_for_process();
+
+			if (terminated != NULL)
+				check_target_completion();
 			continue;
 		}
 
@@ -240,15 +229,10 @@ int main(void)
 				switch (svc->type) {
 				case SVC_WAIT:
 					for (;;) {
-						pid = wait_for_process(&status);
-						if (pid == rt->pid)
+						terminated = wait_for_process();
+						if (terminated == rt)
 							break;
-						supervisor_handle_exited(pid, status);
 					}
-
-					rt->state = status == EXIT_SUCCESS ?
-						STATE_COMPLETED : STATE_FAILED;
-					print_status(svc->desc, rt->state);
 					break;
 				case SVC_ONCE:
 					singleshot += 1;
-- 
cgit v1.2.3