- Implement new ApplicationCore:
- Manage Tools: Log, DataTree, JSONparser & Selector
- Load configuration, Manage FunctionBlocks
- FunctionCore & dirived classes, SignalCore:
- affects: SelectableCore, DeviceCore, FileCore, WatchdogCore
- Do not pass Log()
- Define and pass Type
- Update/reduce included headers
- Use ProcessName and Application global vars
- Get Log, DataTree from Application
- Use virtual Init() function to set must have Channels/Handles
- DataTreeCore:
- Bug fix: Check if child members exist and destroy in SetValuePtr()
- Add method GetFirstChild with BaseMember & Path
- Bug fix: do not use RootMember if no Parent in GetChildxxx() methods
- SignalCore, SelectCore:
- Use Application->Log()
- FunctionCore:
- Add itself to Application (function list)
- Add parameter: LinkConfigMember, Type
- Use virtual LoadConfigData() to configure from DataTree
- Rename methods: LoadConfig() -> InitConfig(),
InitLogging() -> SetLogParam(), SetDebugLevel() -> SetLogLevel()
- Add method: GetType(), LoadChannelLinkData(), InitChannelLinks()
- Modify LinkIn/OutputChannel() to use name for InFunction, not pointer
- SelectableCore & Dirived classes:
- Affects DeviceCore & WatchdogClient
- Rename parameter: Select -> Selector, BaseMember -> ConfigMember
- Get Selector from Application->Selector
- Change Handles JSON structure from Array to Key:Value pairs
- Bug fix: check if Selector exist during Input()
- Bug fix: do not set PortNo if not exist
156 lines
4.8 KiB
C++
156 lines
4.8 KiB
C++
/*
|
|
* SignalCore.cpp
|
|
*
|
|
* Created on: 17 May 2016
|
|
* Author: wentzelc
|
|
*/
|
|
|
|
// redA Libraries
|
|
#include "ApplicationCore.h"
|
|
#include "SignalCore.h"
|
|
|
|
// Standard C/C++ Libraries
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <iostream>
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Global vars
|
|
extern char * ProcessName;
|
|
extern CApplication * Application;
|
|
|
|
// Termination Vars
|
|
bool Terminate = false;
|
|
int TermCount = 0;
|
|
int MaxTermCount = 5;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Configure Signal handling
|
|
void ConfigureSignalHandlers()
|
|
{
|
|
struct sigaction TermAct;
|
|
struct sigaction AbortAct;
|
|
|
|
// Signals to be ignored
|
|
signal( SIGCHLD, SIG_IGN );
|
|
signal( SIGPIPE, SIG_IGN );
|
|
|
|
// Signals for normal termination
|
|
TermAct.sa_handler = SignalTerminate;
|
|
sigemptyset( &TermAct.sa_mask );
|
|
TermAct.sa_flags = SA_RESTART;
|
|
|
|
sigaction( SIGHUP, &TermAct, 0 );
|
|
sigaction( SIGINT, &TermAct, 0 );
|
|
sigaction( SIGQUIT, &TermAct, 0 );
|
|
sigaction( SIGTERM, &TermAct, 0 );
|
|
sigaction( SIGTSTP, &TermAct, 0 );
|
|
|
|
// Signals for immediate termination
|
|
AbortAct.sa_handler = SignalAbort;
|
|
sigemptyset( &AbortAct.sa_mask );
|
|
AbortAct.sa_flags = 0;
|
|
|
|
sigaction( SIGABRT, &AbortAct, 0 );
|
|
sigaction( SIGFPE, &AbortAct, 0 );
|
|
sigaction( SIGILL, &AbortAct, 0 );
|
|
sigaction( SIGSEGV, &AbortAct, 0 );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Signal handler to terminate program the standard way
|
|
void SignalTerminate( int sig )
|
|
{
|
|
char SigName[10];
|
|
|
|
// Determine signal name
|
|
switch (sig)
|
|
{
|
|
case SIGHUP : strcpy( SigName, "SIGHUP " ); break;
|
|
case SIGINT : strcpy( SigName, "SIGINT " ); break;
|
|
case SIGQUIT : strcpy( SigName, "SIGQUIT" ); break;
|
|
case SIGTERM : strcpy( SigName, "SIGTERM" ); break;
|
|
case SIGTSTP : strcpy( SigName, "SIGTSTP" ); break;
|
|
default : strcpy( SigName, "UNKNOWN" ); break;
|
|
}
|
|
|
|
// Allow process to terminate normally
|
|
Terminate = true;
|
|
TermCount++;
|
|
|
|
std::cerr << std::endl << ProcessName << ": ***********************************" << std::endl;
|
|
|
|
// Create Application->Log Entry
|
|
if (Application->Log)
|
|
{
|
|
Application->Log->Message( dlLow, dlLow, "%s: ** %s signal received [%d] **", ProcessName, SigName, TermCount );
|
|
// Check for Terminate Limit
|
|
if (TermCount < MaxTermCount) {
|
|
Application->Log->Message( dlLow, dlLow, "%s: ** Terminating normally... **", ProcessName );
|
|
} else {
|
|
Application->Log->Message( dlLow, dlLow, "%s: ** Terminating immediately! **", ProcessName );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << ProcessName << ": ** " << SigName << " signal received [" << TermCount << "] **" << std::endl;
|
|
// Check for Terminate Limit
|
|
if (TermCount < MaxTermCount) {
|
|
std::cerr << ProcessName << ": ** Terminating normally... **" << std::endl;
|
|
} else {
|
|
std::cerr << ProcessName << ": ** Terminating immediately! **" << std::endl;
|
|
}
|
|
}
|
|
|
|
std::cerr << ProcessName << ": ***********************************" << std::endl << std::endl;
|
|
|
|
// Check for Terminate Limit
|
|
if (TermCount >= MaxTermCount) {
|
|
exit( sig );
|
|
}
|
|
|
|
return;
|
|
}//---------------------------------------------------------------------------
|
|
|
|
// Signal Handler to terminate program immediately
|
|
void SignalAbort( int sig )
|
|
{
|
|
char SigName[10];
|
|
|
|
// Determine Signal name
|
|
switch (sig)
|
|
{
|
|
case SIGABRT : strcpy( SigName, "SIGABRT" ); break;
|
|
case SIGFPE : strcpy( SigName, "SIGFPE " ); break;
|
|
case SIGILL : strcpy( SigName, "SIGILL " ); break;
|
|
case SIGPIPE : strcpy( SigName, "SIGPIPE" ); break;
|
|
case SIGSEGV : strcpy( SigName, "SIGSEGV" ); break;
|
|
default : strcpy( SigName, "UNKNOWN" ); break;
|
|
}
|
|
|
|
// Show signal received
|
|
std::cerr << std::endl << ProcessName << ": ********************************" << std::endl;
|
|
|
|
// Create Application->Log Entry - but don't post
|
|
if (Application->Log) {
|
|
Application->Log->Message( dlLow, dlLow, "%s: ** %s signal received **", ProcessName, SigName );
|
|
Application->Log->Message( dlLow, dlLow, "%s: ** Terminating immediately! **", ProcessName );
|
|
}
|
|
else {
|
|
std::cerr << ProcessName << ": ** " << SigName << " signal received **" << std::endl;
|
|
std::cerr << ProcessName << ": ** Terminating immediately! **" << std::endl;
|
|
}
|
|
|
|
std::cerr << ProcessName << ": ********************************" << std::endl << std::endl;
|
|
|
|
// Terminate with signal
|
|
exit( sig );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|