Added main rutines for killing and waiting for childs' dead.
authorviric@mandarina
Sun, 14 May 2006 16:11:32 +0200
changeset 28 a206baaa3ad5
parent 27 b01603838e42
child 29 e51d10f5ded4
Added main rutines for killing and waiting for childs' dead.
signals.c
syslog.h
syslog_kernel.c
--- a/signals.c	Sun May 14 16:11:01 2006 +0200
+++ b/signals.c	Sun May 14 16:11:32 2006 +0200
@@ -8,7 +8,7 @@
 	int result;
 
 	my_action.sa_handler = SIG_IGN;
-	my_action.sa_flags = SA_NOCLDSTOP;
+	my_action.sa_flags = 0;
 	memset(&my_action.sa_mask, 0, sizeof(my_action.sa_mask));
 
 	result = sigaction(SIGHUP, &my_action, NULL);
@@ -27,3 +27,16 @@
 	result = sigaction(SIGCHLD, &my_action, NULL);
 	assert(result == 0);
 }
+
+void program_handler(int signum, void (*handler)(int))
+{
+	struct sigaction my_action;
+	int result;
+
+	my_action.sa_handler = handler;
+	my_action.sa_flags = 0;
+	memset(&my_action.sa_mask, 0, sizeof(my_action.sa_mask));
+
+	result = sigaction(signum, &my_action, NULL);
+	assert(result == 0);
+}
--- a/syslog.h	Sun May 14 16:11:01 2006 +0200
+++ b/syslog.h	Sun May 14 16:11:32 2006 +0200
@@ -30,3 +30,4 @@
 /* signals.c */
 void program_child_handler(void (*child_handler)(int));
 void program_ignore_hup();
+void program_handler(int signum, void (*handler)(int));
--- a/syslog_kernel.c	Sun May 14 16:11:01 2006 +0200
+++ b/syslog_kernel.c	Sun May 14 16:11:32 2006 +0200
@@ -14,12 +14,11 @@
 #include "syslog.h"
 
 /* Program names */
-const char syslog_in_unix[] = "syslog_in_unix";
-const char syslog_in_npipe[] = "syslog_in_npipe";
-const char syslog_in_udp[] = "syslog_in_udp";
+static const char syslog_in_unix[] = "syslog_in_unix";
+static const char syslog_in_npipe[] = "syslog_in_npipe";
+static const char syslog_in_udp[] = "syslog_in_udp";
 
 /* Global variables */
-bool program_initialized = false;
 
 enum echilds {
 	CHILD_NPIPE,
@@ -28,16 +27,23 @@
 	END_CHILDS
 };
 
-struct {
+static struct {
 	int pid;
 	int input_pipe[2];
 	bool running;
 } child[END_CHILDS];
 
+static int childs_alive = 0;
+
+/* Prototypes */
+static void term_childs();
+
+/* Code */
 static void child_handler(int parameter)
 {
 	pid_t pid;
 	int status;
+	enum echilds i;
 
 	do
 	{
@@ -48,6 +54,7 @@
 			{
 				/* We don't have more childs! */
 				fprintf(stderr, "We don't have more childs.\n");
+				childs_alive = 0;
 				break;
 			} else
 			{
@@ -57,16 +64,30 @@
 			}
 		}
 		/* Debug */
-		if (WIFEXITED(status))
+		if (pid > 0)
 		{
-			fprintf(stderr, "Child %i died fine:%i\n",
-				pid, WEXITSTATUS(status));
-		} else 
-			fprintf(stderr, "Child %i signaled strange: %08x\n",
+			fprintf(stderr, "Child %i died: 0x%08x\n",
 				pid, status);
+			/* We update the child status */
+			for(i=0;i<END_CHILDS;i++)
+			{
+				if(child[i].pid == pid)
+				{
+					child[i].running = false;
+					break;
+				}
+			}
+			childs_alive--;
+		}
 	} while(pid > 0);
 }
 
+static void term_handler(int parameter)
+{
+	term_childs();
+}
+
+
 static int run_program(const char * restrict programname,
 		const char * restrict parameter1, const int comm_pipe[])
 {
@@ -91,6 +112,7 @@
 	{
 		fprintf(stderr, "Child forked(%s %s): %i\n",
 			programname, parameter1, pid);
+		childs_alive++;
 		return pid;
 	}
 }
@@ -183,6 +205,7 @@
 		res_r = read(input_pipe[0], missatge, MESSAGE_LENGTH);
 		errno_r = errno;
 
+		res_w = 1; /* To bypass further error checking */
 		if (res_r > 0)
 		{
 			/* Add a ZERO for displaying */
@@ -202,7 +225,10 @@
 		}
 		else if (res_r == -1 && errno == EINTR)
 			/* The call was interrupted by a signal */
-			continue;
+			if (childs_alive == 0)
+				break;
+			else
+				continue;
 		else /* End of read: res_r -1 or 0 */
 			break;
 	}
@@ -227,8 +253,49 @@
 static void install_signal_handlers()
 {
 	program_child_handler(child_handler);
+	program_handler(SIGTERM, term_handler);
 }
 
+static void term_childs()
+{
+	enum echilds i;
+	int res;
+
+	/* Send SIGTERM */
+	for(i=0;i<END_CHILDS;i++)
+	{
+		if(child[i].running)
+		{
+			res = kill(child[i].pid, SIGTERM);
+			/* Accepting the res == -1 && errno == ESRCH saves us
+			 * from the race condition possible kill error */
+			if (res == -1)
+				assert( errno == ESRCH );
+		}
+	}
+
+}
+
+static void wait_childs_die()
+{
+	/* the signal handler for SIGALRM should be restored here */
+	int total;
+	enum echilds i;
+
+	/* Wait for the end */
+	while(childs_alive > 0)
+	{
+		total=0;
+		for(i=0;i<END_CHILDS;i++)
+		{
+			if(child[i].running)
+				total++;
+		}
+		if (total == 0)
+			break;
+		sleep(1);
+	}
+}
 
 int main(int argn, char *argv[])
 {
@@ -237,4 +304,8 @@
 	init_config();
 
 	kernel_loop();
+
+	term_childs();
+
+	wait_childs_die();
 }