#include <stdio.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sysio/log.h>
#include <getopt.h>
#include <gxPL.h>
#include "version-git.h"
#define MAX_HUB_RESTARTS 10000
static pid_t hub_pid = 0;
static gxPLHub * hub;
static void prvPrintUsage (void);
static void prvSupervisorSignalHandler (int sig);
static void prvHubSignalHandler (int sig);
static void prvParseAdditionnalOptions (int argc, char *argv[]);
int
main (int argc, char * argv[]) {
vLogInit (LOG_UPTO (LOG_NOTICE));
if (setting == NULL) {
prvPrintUsage();
exit (EXIT_FAILURE);
}
prvParseAdditionnalOptions (argc, argv);
vLogDaemonize (true);
switch (fork()) {
case 0:
close (fileno (stdin));
close (fileno (stdout));
close (fileno (stderr));
setpgrp();
prvSuperviseHub (setting);
break;
default:
break;
case -1:
PERROR ("unable to spawn gxpl-hub supervisor, %s (%d)",
strerror (errno), errno);
exit (EXIT_FAILURE);
}
}
else {
if (prvRunHub (setting) != 0) {
exit (EXIT_FAILURE);
}
}
return 0;
}
static int
int ret;
PERROR ("Unable to start the hub");
return -1;
}
signal (SIGTERM, prvHubSignalHandler);
signal (SIGINT, prvHubSignalHandler);
printf ("Starting hub test on xPL port %d for IP below:\n",
for (int i = 0; i < iVectorSize (ip_list); i++) {
printf (" %s\n", (const char *) pvVectorGet (ip_list, i));
}
printf ("Press Ctrl+C to abort ...\n");
}
else {
vLog (LOG_NOTICE, "xPL Hub now running");
}
for (;;) {
if (ret != 0) {
PERROR ("Hub failure, exiting !");
return -1;
}
}
return 0;
}
static void
int hub_restart_count = 0;
int ret;
signal (SIGTERM, prvSupervisorSignalHandler);
signal (SIGINT, prvSupervisorSignalHandler);
for (;;) {
if (hub_restart_count == MAX_HUB_RESTARTS) {
PERROR ("gxpl-hub has died %d times -- something may be wrong "
"-- terminating supervisor", MAX_HUB_RESTARTS);
exit (EXIT_FAILURE);
}
hub_restart_count++;
switch (hub_pid = fork()) {
case 0:
close (fileno (stdin));
close (fileno (stdout));
close (fileno (stderr));
setpgrp();
if (prvRunHub (setting) != 0) {
exit (EXIT_FAILURE);
}
break;
default:
PDEBUG ("spawned gxpl-hub process, pid=%d, spawn count=%d",
hub_pid, hub_restart_count);
break;
case -1:
PERROR ("unable to spawn gxpl-hub supervisor, %s (%d)",
strerror (errno), errno);
exit (EXIT_FAILURE);
}
waitpid (hub_pid, &ret, 0);
if (WIFEXITED (ret)) {
vLog (LOG_NOTICE, "gxpl-hub exited normally with status %d -- restarting...",
WEXITSTATUS (ret));
}
else if (WIFSIGNALED (ret)) {
vLog (LOG_NOTICE, "gxpl-hub died from by receiving unexpected signal %d"
" -- restarting...", WTERMSIG (ret));
}
else {
vLog (LOG_NOTICE, "gxpl-hub died from unknown causes -- restarting...");
}
delay_ms (1000);
}
}
static void
prvPrintUsage (void) {
printf ("%s - xPL Hub\n", __progname);
printf ("Copyright (c) 2015-2016 epsilonRT \n\n");
printf ("Usage: %s [-i interface] [-d] [-D] [-h]\n", __progname);
printf (" -i interface - use interface named interface (i.e. eth0) as network interface\n");
printf (" -W timeout - set the timeout at the opening of the io layer\n");
printf (" -D - do not daemonize -- run from the console\n");
printf (" -d - enable debugging, it can be doubled or tripled to"
" increase the level of debug. \n");
printf (" -h - print this message\n\n");
}
static void
prvHubSignalHandler (int sig) {
int ret;
switch (sig) {
case SIGTERM:
case SIGINT:
if (ret != 0) {
PERROR ("unable to close hub");
exit (EXIT_FAILURE);
}
vLog (LOG_NOTICE, "everything was closed. Have a nice day !");
exit (EXIT_SUCCESS);
break;
default:
break;
}
}
static void
prvSupervisorSignalHandler (int sig) {
int ret;
vLog (LOG_NOTICE, "received termination signal -- starting shutdown");
switch (sig) {
case SIGTERM:
case SIGINT:
if ( (hub_pid != 0) && (kill (hub_pid, SIGTERM) == 0)) {
waitpid (hub_pid, &ret, 0);
if (WIFEXITED (ret) == 0) {
exit (EXIT_FAILURE);
}
}
exit (EXIT_SUCCESS);
break;
default:
break;
}
}
static void
prvParseAdditionnalOptions (int argc, char *argv[]) {
int c;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{NULL, 0, NULL, 0}
};
do {
c = getopt_long (argc, argv, short_options, long_options, NULL);
switch (c) {
case 'h':
prvPrintUsage();
exit (EXIT_SUCCESS);
break;
default:
break;
}
}
while (c != -1);
}