aped watchdog - APE-Project/APE_Server GitHub Wiki

Set the SBIN_DIR define to the location of the bin folder for your APE server and compile it with

#include <sys/wait.h>
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>

#define SBIN_DIR "/home/para/APE_rev/dir_2/APE_Server/bin"
#define BINPATH SBIN_DIR"/aped"

static volatile sig_atomic_t start_process = 1;
static volatile pid_t pid = -1;
#define UNUSED(x) ( (void)(x) )

static void sigaction_handler(int sig, siginfo_t *si, void *context) {
	int exitcode;
	UNUSED(context);
	switch (sig) {
		case SIGINT:
		case SIGTERM:
			/** forward the sig to the child */
			kill(pid, sig);
			break;
		case SIGHUP: /** do a graceful restart */
			/** do a graceful shutdown on the main process and start a new child */
			kill(pid, SIGINT);
			usleep(5 * 1000); /** wait 5 microsec */
			start_process = 1;
			break;
		case SIGCHLD:
			/** a child died, de-combie it */
			wait(&exitcode);
			break;
	}
}

int main(int argc, char **argv) {
	int is_shutdown = 0;
	struct sigaction act;
	
	UNUSED(argc);
	/**
	* we are running as root BEWARE
	*/
	memset(&act, 0, sizeof(act));
	act.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &act, NULL);
	sigaction(SIGUSR1, &act, NULL);

	act.sa_sigaction = sigaction_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_SIGINFO;
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);
	sigaction(SIGHUP, &act, NULL);
	sigaction(SIGALRM, &act, NULL);
	sigaction(SIGCHLD, &act, NULL);
	/* check that the compiled in path has the right user,
	*
	* BEWARE: there is a race between the check here and the exec later
	*/
	while (!is_shutdown) {
		int exitcode = 0;
		if (start_process) {
			pid = fork();
			if (0 == pid) {
				/* i'm the child */
				argv[0] = BINPATH;
				execvp(BINPATH, argv);
				exit(1);
			} else if (-1 == pid) {
				/** error */
				return -1;
			}
			/* I'm the angel */
			start_process = 0;
		}
		if ((pid_t)-1 == waitpid(pid, &exitcode, 0)) {
			switch (errno) {
				case EINTR:
					/* someone sent a signal ...
					* do we have to shutdown or restart the process */
					break;
				case ECHILD:
					/**
					* make sure we are not in a race between the signal handler
					* and the process restart */
					if (!start_process) is_shutdown = 1;
					break;
				default:
					break;
			}
		} else {
			/** process went away */
			if (WIFEXITED(exitcode)) {
				/** normal exit */
				is_shutdown = 1;
			fprintf(stderr, "%s.%d: child (pid=%d) exited normally with exitcode: %d\n", __FILE__, __LINE__, pid, WEXITSTATUS(exitcode));
			} else if (WIFSIGNALED(exitcode)) {
				/** got a signal */
				fprintf(stderr, "%s.%d: child (pid=%d) exited unexpectedly with signal %d, restarting\n", __FILE__, __LINE__, pid, WTERMSIG(exitcode));
				start_process = 1;
			}
		}
	}

	return 0;
}
gcc watchdog.c -o aped_watchdog

Then launch your APE Server with

./aped_watchdog

The file ape.conf has to be in the same directory, If it's not the case specify the path to ape.conf with --cfg arguments.

./aped_watchdog --cfg /path/to/ape.conf
⚠️ **GitHub.com Fallback** ⚠️