/*
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
*
* This program is provided under the terms of the Common Public License,
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
* found in the file LICENSE file or at
* https://opensource.org/licenses/cpl1.0.php
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "log.h"
#include "slotmgr.h"
#include "pkcsslotd.h"
#include "err.h"
extern BOOL IsValidProcessEntry(pid_t_64 pid, time_t_64 RegTime);
static int SigsToIntercept[] = {
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM,
SIGTERM, SIGTSTP, SIGTTIN,
SIGTTOU, SIGUSR1, SIGUSR2, SIGPROF
};
/* SIGCONT - Don't want to exit on SIGCONT; it'll in fact
mask other signals - kill -HUP actually sends SIGCONT before SIGHUP */
/* SIGCHLD - Don't want to exit. Should never receive, but we do, apparently
* when something tries to cancel the GC Thread */
static int SigsToIgnore[] = {
SIGCHLD,
};
/**************************************************
* slotdGenericSignalHandler
*
* Main signal handler for the daemon. Doesn't
* allow the daemon to be killed unless we're
* not in use
***************************************************/
void slotdGenericSignalHandler(int Signal)
{
int procindex;
BOOL OkToExit = TRUE;
/********************************************************
* DbgLog calls (possibly) printf, syslog_r, etc.
* The behavior of these functions is "undefined"
* when called from a signal handler according to
* the sigaction man page.
*
* Thus, they're only called in development
* versions of the code.
********************************************************/
#ifdef DEV
DbgLog(DL2, "slotdGenericSignalHandler got %s (%d; %#x)",
SignalConst(Signal), Signal, Signal);
#endif /* DEV */
#if !defined(NOGARBAGE)
StopGCThread(shmp);
CheckForGarbage(shmp);
#endif
for (procindex = 0; (procindex < NUMBER_PROCESSES_ALLOWED); procindex++) {
Slot_Mgr_Proc_t_64 *pProc = &(shmp->proc_table[procindex]);
if (shmp == NULL) {
break;
}
if ((pProc->inuse)
#if !(NOGARBAGE)
&& (IsValidProcessEntry(pProc->proc_id, pProc->reg_time))
#endif
) {
/* Someone's still using us... Log it */
OkToExit = FALSE;
#ifdef DEV
WarnLog("Process %d is still registered", pProc->proc_id);
#endif
}
}
if (!OkToExit) {
DbgLog(DL1, "Continuing execution");
#if !defined(NOGARBAGE)
StartGCThread(shmp);
#endif
return;
}
InfoLog("Exiting on %s (%d; %#x)", SignalConst(Signal), Signal, Signal);
DetachSocketListener(socketfd);
DestroyMutexes();
DetachFromSharedMemory();
DestroySharedMemory();
exit(0);
}
/***************************************************
* SetupSignalHandlers -
*
* Installs slotdGenericSignalHandler for the listed signals
*
***************************************************/
int SetupSignalHandlers(void)
{
unsigned int i;
struct sigaction new_action;
new_action.sa_handler = slotdGenericSignalHandler;
sigemptyset(&(new_action.sa_mask));
sigaddset(&(new_action.sa_mask), SIGCHLD);
/* sigaddset(&(new_action.sa_mask), SA_NOCLDWAIT); */
/* sigaddset(&(new_action.sa_mask), SA_NOCLDSTOP); */
new_action.sa_flags = (RESTART_SYS_CALLS ? SA_RESTART : 0);
for (i = 0;
i < (sizeof(SigsToIntercept) / sizeof(SigsToIntercept[0])); i++) {
if (sigaction(SigsToIntercept[i], &new_action, NULL) != 0) {
//DbgLog("SetupSignalHandlers - sigaction failed for %s (%d; %#x)",
//SignalConst(SigsToIntercept[i]),
//SigsToIntercept[i], SigsToIntercept[i]);
return FALSE;
}
}
new_action.sa_handler = SIG_IGN;
sigemptyset(&(new_action.sa_mask));
for (i = 0; i < (sizeof(SigsToIgnore) / sizeof(SigsToIgnore[0])); i++) {
if (sigaction(SigsToIgnore[i], &new_action, NULL) != 0) {
//DbgLog ( "Failed to ignore signal.");
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* GCBlockSignals -
*
* Garbage collector calls this to prevent signals from getting
* sent to the GC thread.
*
***********************************************************************/
BOOL GCBlockSignals(void)
{
unsigned int i;
int ret;
sigset_t SigSet;
sigemptyset(&SigSet);
for (i = 0;
i < (sizeof(SigsToIntercept) / sizeof(SigsToIntercept[0])); i++) {
sigaddset(&SigSet, SigsToIntercept[i]);
}
ret = pthread_sigmask(SIG_SETMASK, &SigSet, NULL);
return ret;
}