Separated the child handling in another module.
Now the child handling is more dynamic than before.
--- 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;