Separated the child handling in another module.
authorviric@llimona
Mon, 29 May 2006 23:58:47 +0200
changeset 49 ced312cc1eaa
parent 48 00a2a7055f2f
child 50 6958ce45aa83
Separated the child handling in another module. Now the child handling is more dynamic than before.
Makefile.common
childs.c
syslog.h
syslog_kernel.c
--- a/Makefile.common	Mon May 15 18:08:54 2006 +0200
+++ b/Makefile.common	Mon May 29 23:58:47 2006 +0200
@@ -20,12 +20,14 @@
 out_file.o: out_file.c syslog.h
 signals.o: signals.c syslog.h
 unix_writer.o: unix_writer.c rfc3164.h
+childs.o: childs.c syslog.h
 
 syslog_in_npipe: syslog_in_npipe.o rfc3164.a signals.o
 syslog_in_udp: syslog_in_udp.o rfc3164.a signals.o
 syslog_in_unix: syslog_in_unix.o rfc3164.a signals.o
 unix_writer: unix_writer.o
-syslog_kernel: syslog_kernel.o config.o rfc3164.a signals.o out_udp.o out_file.o
+syslog_kernel: syslog_kernel.o config.o rfc3164.a signals.o out_udp.o \
+               out_file.o childs.o
 
 clean:
 	rm -f *.o *.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/childs.c	Mon May 29 23:58:47 2006 +0200
@@ -0,0 +1,161 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/wait.h> // Per wait
+#include <assert.h> // Pels assert
+
+#include "syslog.h"
+
+/* Variables */
+int childs_alive = 0;
+
+static int child[MAX_CHILDS];
+
+
+/* Prototypes */
+static void remove_child(const int pid);
+
+/* Code */
+void term_childs()
+{
+	int res;
+	int i;
+
+	sigset_t tmp, normal;
+
+	/* block the child signals */
+	sigemptyset(&tmp);
+	sigaddset(&tmp, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &tmp, &normal);
+
+	/* Send SIGTERM */
+	for(i=0;i<childs_alive;i++)
+	{
+		res = kill(child[i], SIGTERM);
+		/* Accepting the res == -1 && errno == ESRCH saves us
+		 * from the race condition possible kill error */
+		if (res == -1)
+			assert( errno == ESRCH );
+	}
+
+	/* restore the mask */
+	sigprocmask(SIG_SETMASK, &normal, NULL);
+
+}
+
+void wait_childs_die()
+{
+	/* Wait for the end */
+	while(childs_alive > 0)
+	{
+		sleep(1);
+	}
+}
+
+void child_handler(int parameter)
+{
+	pid_t pid;
+	int status;
+
+	do
+	{
+		pid = waitpid(-1, &status, WNOHANG);
+		if (pid == -1)
+		{
+			if(errno == ECHILD)
+			{
+				/* We don't have more childs! */
+				fprintf(stderr, "We don't have more childs.\n");
+				childs_alive = 0;
+				break;
+			} else
+			{
+				fprintf(stderr, "waitpid failed. %s\n",
+					strerror(errno));
+				break;
+			}
+		}
+		/* Debug */
+		if (pid > 0)
+		{
+			fprintf(stderr, "Child %i died: 0x%08x\n",
+				pid, status);
+			remove_child(pid);
+		}
+	} while(pid > 0);
+}
+
+int child_fork()
+{
+	int pid;
+	sigset_t tmp, normal;
+
+	/* block the child signals */
+	sigemptyset(&tmp);
+	sigaddset(&tmp, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &tmp, &normal);
+
+
+	if (childs_alive < MAX_CHILDS)
+	{
+		pid = fork();
+	}
+	else
+	{
+		pid = -1;
+	}
+
+	if (pid > 0)
+	{
+		/* Parent */
+
+		/* MUTEX-ed actions with the SIGCHLD handler */
+		child[childs_alive++] = pid;
+	}
+
+	/* restore the mask */
+	sigprocmask(SIG_SETMASK, &normal, NULL);
+
+	return pid;
+}
+
+/* This will be called only from the SIGCHLD handler */
+static void remove_child(const int pid)
+{
+	int i;
+
+	/* We update the child status */
+	for(i=0;i<childs_alive;i++)
+	{
+		if(child[i] == pid)
+			break;
+	}
+
+	for(i = i; i < (childs_alive-1); i++)
+	{
+		child[i] = child[i+1];
+	}
+
+	childs_alive--;
+}
+
+int get_childs_alive()
+{
+	int num;
+	sigset_t tmp, normal;
+
+	/* block the child signals */
+	sigemptyset(&tmp);
+	sigaddset(&tmp, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &tmp, &normal);
+
+	num = childs_alive;
+
+	/* restore the mask */
+	sigprocmask(SIG_SETMASK, &normal, NULL);
+
+	return num;
+}
--- a/syslog.h	Mon May 15 18:08:54 2006 +0200
+++ b/syslog.h	Mon May 29 23:58:47 2006 +0200
@@ -1,5 +1,6 @@
 enum {
-	MAX_STRING=255
+	MAX_STRING=255,
+	MAX_CHILDS=15
 };
 
 enum etype_config
@@ -20,7 +21,6 @@
 	char value[MAX_STRING]; /* Value of the parameter */
 };
 
-
 /* Prototypes -------------------- */
 
 /* config.c */
@@ -41,3 +41,10 @@
 int init_out_file();
 int write_out_file(const char * restrict buf, const int len);
 int close_out_file();
+
+/* childs.c */
+void term_childs();
+void wait_childs_die();
+void child_handler(int parameter);
+int child_fork();
+int get_childs_alive();
--- a/syslog_kernel.c	Mon May 15 18:08:54 2006 +0200
+++ b/syslog_kernel.c	Mon May 29 23:58:47 2006 +0200
@@ -2,8 +2,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <stdbool.h>
+#include <signal.h>
 #include <stdio.h> // Per sprintf, fprintf
-#include <sys/wait.h> // Per wait
 #include <string.h> // Per memset
 #include <assert.h> // Pels assert
 #include <stdlib.h> // Per l'abort
@@ -20,70 +20,9 @@
 static const char syslog_in_udp[] = "syslog_in_udp";
 
 /* Global variables */
-
-enum echilds {
-	CHILD_NPIPE,
-	CHILD_UNIX,
-	CHILD_UDP,
-	END_CHILDS
-};
-
-static struct {
-	int pid;
-	int input_pipe[2];
-	bool running;
-} child[END_CHILDS];
-
-static int childs_alive = 0;
 static bool reconfig = false;
 
-/* Prototypes */
-static void term_childs();
-
 /* Code */
-static void child_handler(int parameter)
-{
-	pid_t pid;
-	int status;
-	enum echilds i;
-
-	do
-	{
-		pid = waitpid(-1, &status, WNOHANG);
-		if (pid == -1)
-		{
-			if(errno == ECHILD)
-			{
-				/* We don't have more childs! */
-				fprintf(stderr, "We don't have more childs.\n");
-				childs_alive = 0;
-				break;
-			} else
-			{
-				fprintf(stderr, "waitpid failed. %s\n",
-					strerror(errno));
-				break;
-			}
-		}
-		/* Debug */
-		if (pid > 0)
-		{
-			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();
@@ -100,7 +39,7 @@
 {
 	int pid;
 
-	pid = fork();
+	pid = child_fork();
 	assert(pid != -1);
 	if (pid == 0)
 	{
@@ -119,7 +58,6 @@
 	{
 		fprintf(stderr, "Child forked(%s %s): %i\n",
 			programname, parameter1, pid);
-		childs_alive++;
 		return pid;
 	}
 }
@@ -148,35 +86,17 @@
 	/* The childs should not run */
 	if (get_config(FROM_UNIX, cvalue, MAX_STRING) > 0)
 	{
-		child[CHILD_UNIX].input_pipe[0] = input_pipe[0];
-		child[CHILD_UNIX].input_pipe[1] = input_pipe[1];
-		child[CHILD_UNIX].pid = init_in_unix(cvalue, input_pipe);
-		if (child[CHILD_UNIX].pid == 0)
-			child[CHILD_UNIX].running = false;
-		else
-			child[CHILD_UNIX].running = true;
+		init_in_unix(cvalue, input_pipe);
 	}
 
 	if (get_config(FROM_NPIPE, cvalue, MAX_STRING) > 0)
 	{
-		child[CHILD_NPIPE].input_pipe[0] = input_pipe[0];
-		child[CHILD_NPIPE].input_pipe[1] = input_pipe[1];
-		child[CHILD_NPIPE].pid = init_in_npipe(cvalue, input_pipe);
-		if (child[CHILD_NPIPE].pid == 0)
-			child[CHILD_NPIPE].running = false;
-		else
-			child[CHILD_NPIPE].running = true;
+		init_in_npipe(cvalue, input_pipe);
 	}
 
 	if (get_config(FROM_UDP, cvalue, MAX_STRING) > 0)
 	{
-		child[CHILD_UDP].input_pipe[0] = input_pipe[0];
-		child[CHILD_UDP].input_pipe[1] = input_pipe[1];
-		child[CHILD_UDP].pid = init_in_udp(cvalue, input_pipe);
-		if (child[CHILD_UDP].pid == 0)
-			child[CHILD_UDP].running = false;
-		else
-			child[CHILD_UDP].running = true;
+		init_in_udp(cvalue, input_pipe);
 	}
 }
 
@@ -232,7 +152,7 @@
 		}
 
 		/* The select call may be interrupted by a signal */
-		if (childs_alive == 0)
+		if (get_childs_alive() == 0)
 			break;
 
 		if (reconfig == true)
@@ -264,47 +184,6 @@
 	program_handler(SIGHUP, reconfig_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[])
 {
 	int res;