/*
* Soft: Keepalived is a failover program for the LVS project
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
*
* Part: Signals framework.
*
* Version: $Id: signals.c,v 1.1.1.1 2005/03/01 00:23:00 clement Exp $
*
* Author: Kevin Lindsay, <kevinl@netnation.com>
* Alexandre Cassen, <acassen@linux-vs.org>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Copyright (C) 2001-2005 Alexandre Cassen, <acassen@linux-vs.org>
*/
#include <signal.h>
#include <string.h>
#include "signals.h"
/* Local Vars */
static int signal_mask;
void (*signal_SIGHUP_handler) (int sig);
void (*signal_SIGINT_handler) (int sig);
void (*signal_SIGTERM_handler) (int sig);
void (*signal_SIGCHLD_handler) (int sig);
/* Local signal test */
int
signal_pending(void)
{
return (signal_mask) ? 1 : 0;
}
/* Signal flag */
void
signal_handler(int sig)
{
switch(sig) {
case SIGHUP:
signal_mask |= SIGNAL_SIGHUP;
break;
case SIGINT:
signal_mask |= SIGNAL_SIGINT;
break;
case SIGTERM:
signal_mask |= SIGNAL_SIGTERM;
break;
case SIGCHLD:
signal_mask |= SIGNAL_SIGCHLD;
break;
}
}
/* Signal wrapper */
void *
signal_set(int signo, void (*func) (int))
{
int ret;
struct sigaction sig;
struct sigaction osig;
sig.sa_handler = signal_handler;
sigemptyset(&sig.sa_mask);
sig.sa_flags = 0;
#ifdef SA_RESTART
sig.sa_flags |= SA_RESTART;
#endif /* SA_RESTART */
ret = sigaction(signo, &sig, &osig);
switch(signo) {
case SIGHUP:
signal_SIGHUP_handler = func;
break;
case SIGINT:
signal_SIGINT_handler = func;
break;
case SIGTERM:
signal_SIGTERM_handler = func;
break;
case SIGCHLD:
signal_SIGCHLD_handler = func;
break;
}
if (ret < 0)
return (SIG_ERR);
else
return (osig.sa_handler);
}
/* Signal Ignore */
void *
signal_ignore(int signo)
{
return signal_set(signo, SIG_IGN);
}
/*
* SIGCHLD handler. Reap all zombie child.
* WNOHANG prevent against parent process get
* stuck waiting child termination.
*/
void
dummy_handler(int sig)
{
/* Dummy */
}
void
signal_noignore_sigchld(void)
{
struct sigaction sa;
sigset_t mask;
/* Need to remove the NOCHLD flag */
sigemptyset(&mask);
sa.sa_handler = dummy_handler;
sa.sa_mask = mask;
sa.sa_flags = 0;
sigaction(SIGCHLD, &sa, NULL);
/* Block SIGCHLD so that we only receive it
* when required (ie when its unblocked in the
* select loop)
*/
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, NULL);
}
/* Handlers intialization */
void
signal_handler_init(void)
{
signal_mask = 0;
signal_SIGHUP_handler = NULL;
signal_SIGINT_handler = NULL;
signal_SIGTERM_handler = NULL;
signal_SIGCHLD_handler = NULL;
}
/* Handlers callback according to global signal mask */
void
signal_run_callback(void)
{
if (SIGNAL_SIGHUP & signal_mask) {
signal_mask &= ~SIGNAL_SIGHUP;
if (signal_SIGHUP_handler)
signal_SIGHUP_handler(SIGHUP);
}
if (SIGNAL_SIGINT & signal_mask) {
signal_mask &= ~SIGNAL_SIGINT;
if (signal_SIGINT_handler)
signal_SIGINT_handler(SIGINT);
}
if (SIGNAL_SIGTERM & signal_mask) {
signal_mask &= ~SIGNAL_SIGTERM;
if (signal_SIGTERM_handler)
signal_SIGTERM_handler(SIGTERM);
}
if (SIGNAL_SIGCHLD & signal_mask) {
signal_mask &= ~SIGNAL_SIGCHLD;
if (signal_SIGCHLD_handler)
signal_SIGCHLD_handler(SIGCHLD);
}
}
syntax highlighted by Code2HTML, v. 0.9.1