Added the setsockopt for IPV6_V6ONLY, in order to have IPv6 and IPv4 in two
different sockets for the same port.
#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 */
static 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);
fprintf(stderr, "Sent SIGTERM to %i\n", child[i]);
/* 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;
}