- merging in Dave's selfDetect branch so we can limit our components to only a single instance
- small changes to log messages, passing signal information through to the log and also echoing failed starts to to cout - a HACK was needed to avoid signal 17, Dave can smooth this out in a more intelligent way than my workaround - ticket #1549
This commit is contained in:
parent
4575b4d264
commit
414179aa82
|
@ -18,3 +18,5 @@ SocketsTest
|
||||||
TimevalTest
|
TimevalTest
|
||||||
URLEncodeTest
|
URLEncodeTest
|
||||||
VectorTest
|
VectorTest
|
||||||
|
SelfDetectTest
|
||||||
|
UnixSignalTest
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXIT_H
|
||||||
|
#define EXIT_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
/** A C++ wrapper for managing exit codes. Note that this is a helper class
|
||||||
|
* without implementation.
|
||||||
|
*/
|
||||||
|
class Exit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum eCodes
|
||||||
|
{
|
||||||
|
SUCCESS = 0, // no error
|
||||||
|
DETECTFILE, // Unable to detect a required file: CommonLibs SelfDetect
|
||||||
|
CREATEFILE, // Unable to create a required file: CommonLibs SelfDetect
|
||||||
|
|
||||||
|
// Put all error codes above this line, to prevent error number values
|
||||||
|
// from changing, put after the previous enum value (ie, preserve
|
||||||
|
// the order. Also, provide a comment indicating which program(s) and
|
||||||
|
// the purpose.
|
||||||
|
|
||||||
|
LIMIT = 256 // all error codes must be less than this
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
inline Exit(void) { /* cannot be constructed */; };
|
||||||
|
inline ~Exit(void) { /* cannot be destructed */; };
|
||||||
|
public:
|
||||||
|
inline static void exit(int status)
|
||||||
|
{
|
||||||
|
if (status < SUCCESS || status >= LIMIT)
|
||||||
|
{
|
||||||
|
printf("INFO: Unsupported exit status of %d\n", status);
|
||||||
|
}
|
||||||
|
::exit(status);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // EXIT_H
|
||||||
|
// vim: ts=4 sw=4
|
14
Makefile.am
14
Makefile.am
|
@ -31,8 +31,11 @@ EXTRA_DIST = \
|
||||||
noinst_LTLIBRARIES = libcommon.la
|
noinst_LTLIBRARIES = libcommon.la
|
||||||
|
|
||||||
libcommon_la_SOURCES = \
|
libcommon_la_SOURCES = \
|
||||||
|
Variables.cpp \
|
||||||
BitVector.cpp \
|
BitVector.cpp \
|
||||||
LinkedLists.cpp \
|
LinkedLists.cpp \
|
||||||
|
SelfDetect.cpp \
|
||||||
|
UnixSignal.cpp \
|
||||||
Sockets.cpp \
|
Sockets.cpp \
|
||||||
Threads.cpp \
|
Threads.cpp \
|
||||||
Timeval.cpp \
|
Timeval.cpp \
|
||||||
|
@ -46,6 +49,8 @@ libcommon_la_SOURCES = \
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
BitVectorTest \
|
BitVectorTest \
|
||||||
InterthreadTest \
|
InterthreadTest \
|
||||||
|
SelfDetectTest \
|
||||||
|
UnixSignalTest \
|
||||||
SocketsTest \
|
SocketsTest \
|
||||||
TimevalTest \
|
TimevalTest \
|
||||||
RegexpTest \
|
RegexpTest \
|
||||||
|
@ -62,6 +67,9 @@ noinst_HEADERS = \
|
||||||
BitVector.h \
|
BitVector.h \
|
||||||
Interthread.h \
|
Interthread.h \
|
||||||
LinkedLists.h \
|
LinkedLists.h \
|
||||||
|
SelfDetect.h \
|
||||||
|
UnixSignal.h \
|
||||||
|
Exit.h \
|
||||||
Sockets.h \
|
Sockets.h \
|
||||||
Threads.h \
|
Threads.h \
|
||||||
Timeval.h \
|
Timeval.h \
|
||||||
|
@ -101,6 +109,12 @@ RegexpTest_LDADD = libcommon.la
|
||||||
ConfigurationTest_SOURCES = ConfigurationTest.cpp
|
ConfigurationTest_SOURCES = ConfigurationTest.cpp
|
||||||
ConfigurationTest_LDADD = libcommon.la $(SQLITE_LA)
|
ConfigurationTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
|
SelfDetectTest_SOURCES = SelfDetectTest.cpp
|
||||||
|
SelfDetectTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
|
UnixSignalTest_SOURCES = UnixSignalTest.cpp
|
||||||
|
UnixSignalTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
# ReportingTest_SOURCES = ReportingTest.cpp
|
# ReportingTest_SOURCES = ReportingTest.cpp
|
||||||
# ReportingTest_LDADD = libcommon.la $(SQLITE_LA)
|
# ReportingTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/**@file Module for preventing two instances of a program from running. */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
* See the COPYING file in the main directory for details.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "UnixSignal.h"
|
||||||
|
#include "SelfDetect.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "Exit.h"
|
||||||
|
|
||||||
|
//SelfDetect gSelf;
|
||||||
|
|
||||||
|
static void e(void)
|
||||||
|
{
|
||||||
|
gSelf.Exit(-999);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigfcn(int sig)
|
||||||
|
{
|
||||||
|
gSelf.Exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelfDetect::RegisterProgram(const char *argv0)
|
||||||
|
{
|
||||||
|
const char *p = argv0 + strlen(argv0); // point to end of string
|
||||||
|
while (p > argv0 && *p != '/') p--;
|
||||||
|
if (*p == '/') p++;
|
||||||
|
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
snprintf(buf, sizeof(buf)-1, "/var/run/%s.pid", p);
|
||||||
|
LOG(NOTICE) << "*** Registering program " << argv0 << " to " << buf;
|
||||||
|
|
||||||
|
// first, verify we aren't already running.
|
||||||
|
struct stat stbuf;
|
||||||
|
if (stat(buf, &stbuf) >= 0)
|
||||||
|
{
|
||||||
|
LOG(ERR) << "*** An instance of " << p << " is already running. ";
|
||||||
|
LOG(ERR) << "*** If this is not the case, deleting this file will allow " << p << " to start: " << buf;
|
||||||
|
std::cout << "*** An instance of " << p << " is already running. " << std::endl;
|
||||||
|
std::cout << "*** If this is not the case, deleting this file will allow " << p << " to start: " << buf << std::endl;
|
||||||
|
Exit::exit(Exit::DETECTFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(buf, "w");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
LOG(ERR) << "*** Unable to create " << buf << ": " << strerror(errno);
|
||||||
|
Exit::exit(Exit::CREATEFILE);
|
||||||
|
}
|
||||||
|
fprintf(fp, "%d\n", getpid());
|
||||||
|
fclose(fp);
|
||||||
|
atexit(e);
|
||||||
|
|
||||||
|
// Now, register for all signals to do the cleanup
|
||||||
|
for (int i = 1; i < UnixSignal::C_NSIG; i++)
|
||||||
|
{
|
||||||
|
// HACK because a signal 17 is thrown during a correct initiation of OpenBTS and transceiver
|
||||||
|
// openbts: ALERT 3073816320 05:03:50.4 OpenBTS.cpp:491:main: starting the transceiver
|
||||||
|
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:91:Exit: *** Terminating because of signal 17
|
||||||
|
// openbts: NOTICE 3031243584 05:03:50.4 OpenBTS.cpp:165:startTransceiver: starting transceiver ./transceiver w/ 1 ARFCNs and Args:
|
||||||
|
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:98:Exit: *** Terminating ./OpenBTS
|
||||||
|
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:105:Exit: *** Removing pid file /var/run/OpenBTS.pid
|
||||||
|
if (i == 17) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gSigVec.Register(sigfcn, i);
|
||||||
|
}
|
||||||
|
mProg = strdup(argv0);
|
||||||
|
mFile = strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelfDetect::Exit(int sig)
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Terminating because of signal " << sig;
|
||||||
|
|
||||||
|
if (mProg == NULL)
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Terminating without registration of program";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Terminating " << mProg;
|
||||||
|
}
|
||||||
|
if (mFile == NULL)
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Terminating without pid file";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Removing pid file " << mFile;
|
||||||
|
unlink(mFile);
|
||||||
|
}
|
||||||
|
for (std::list<std::string>::iterator i = mListFiles.begin();
|
||||||
|
i != mListFiles.end(); ++i)
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Removing " << i->c_str();
|
||||||
|
unlink(i->c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelfDetect::RegisterFile(const char *file)
|
||||||
|
{
|
||||||
|
LOG(NOTICE) << "*** Registering " << file << " for removal at program exit";
|
||||||
|
std::string s(file);
|
||||||
|
mListFiles.push_back(s);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Range Networks, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SELFDETECT_H
|
||||||
|
#define SELFDETECT_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
/** A C++ wrapper for preventing 2 instances of a program from running. */
|
||||||
|
class SelfDetect
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const char *mProg; // program name, which will map to /tmp/%s.pid
|
||||||
|
const char *mFile; // file in /tmp for pid
|
||||||
|
std::list<std::string> mListFiles; // list of files to be removed at shutdown
|
||||||
|
public:
|
||||||
|
SelfDetect(void)
|
||||||
|
{
|
||||||
|
mProg = NULL;
|
||||||
|
mFile = NULL;
|
||||||
|
mListFiles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SelfDetect(void)
|
||||||
|
{
|
||||||
|
if (mProg) { free((void *)mProg); mProg = NULL; }
|
||||||
|
if (mFile) { free((void *)mFile); mFile = NULL; }
|
||||||
|
mListFiles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterProgram(const char *argv0); // register the program and validate
|
||||||
|
void RegisterFile(const char *file); // register a file to be removed at shutdown / exit
|
||||||
|
|
||||||
|
void Exit(int); // atexit() registration function -- called internally by real atexit() function that isn't in a class
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SelfDetect gSelf;
|
||||||
|
#endif // SELFDETECT_H
|
||||||
|
// vim: ts=4 sw=4
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
* See the COPYING file in the main directory for details.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "SelfDetect.h"
|
||||||
|
#include "Configuration.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
ConfigurationTable gConfig;
|
||||||
|
|
||||||
|
// For best effects, run this program thrice: once with a pre-created
|
||||||
|
// /var/run/argv.pid, and once without. First one should exit with an
|
||||||
|
// error. Second should run this test. Third, with an argument, then type
|
||||||
|
// Control-C.
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
gLogInit("SelfDetectTest","DEBUG",LOG_LOCAL7);
|
||||||
|
gSelf.RegisterProgram(argv[0]);
|
||||||
|
|
||||||
|
ret = system("touch /tmp/foo.1");
|
||||||
|
ret = system("touch /tmp/foo.2");
|
||||||
|
ret = system("touch /tmp/foo.3");
|
||||||
|
ret = system("touch /tmp/foo.4");
|
||||||
|
ret = system("touch /tmp/foo.5");
|
||||||
|
ret = system("touch /tmp/foo.6");
|
||||||
|
ret = system("touch /tmp/foo.7");
|
||||||
|
if (ret < 0) { ret = ret; } // warning eater
|
||||||
|
|
||||||
|
gSelf.RegisterFile("/tmp/foo.0"); // ignored
|
||||||
|
gSelf.RegisterFile("/tmp/foo.1"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.2"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.3"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.4"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.5"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.6"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.7"); // removed
|
||||||
|
gSelf.RegisterFile("/tmp/foo.8"); // ignored
|
||||||
|
gSelf.RegisterFile("/tmp/foo.9"); // ignored
|
||||||
|
|
||||||
|
if (argv[1] != NULL)
|
||||||
|
{
|
||||||
|
printf("Use a Control-C to test in this mode, make sure\n");
|
||||||
|
printf("that the file goes away\n");
|
||||||
|
while(1)
|
||||||
|
sleep(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/**@file Module for managing Linux signals and allowing multiple handlers per signal. */
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
* See the COPYING file in the main directory for details.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "UnixSignal.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
//UnixSignal gSigVec;
|
||||||
|
|
||||||
|
static void _sigHandler(int sig)
|
||||||
|
{
|
||||||
|
signal(sig, SIG_IGN);
|
||||||
|
if (sig <= 0 || sig >= UnixSignal::C_NSIG)
|
||||||
|
{
|
||||||
|
LOG(ERR) << "Signal Handler for signal " << sig << " (out of range)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// work around C++ issue with function pointers and class based function pointers
|
||||||
|
gSigVec.Handler(sig);
|
||||||
|
signal(sig, SIG_DFL);
|
||||||
|
printf("Rethrowing signal %d\n", sig);
|
||||||
|
kill(getpid(), sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixSignal::Handler(int sig)
|
||||||
|
{
|
||||||
|
//TODO: Code should go here to generate the core file, before we change too
|
||||||
|
// much of the data in the program.
|
||||||
|
|
||||||
|
printf("Processing signal vector for sig %d\n", sig);
|
||||||
|
mLock[sig].lock();
|
||||||
|
for (std::list<sighandler_t>::iterator i = mListHandlers[sig].begin();
|
||||||
|
i != mListHandlers[sig].end(); i++)
|
||||||
|
{
|
||||||
|
(*i)(sig);
|
||||||
|
}
|
||||||
|
mLock[sig].unlock();
|
||||||
|
printf("Done processing signal vector for sig %d\n", sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixSignal::UnixSignal(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < C_NSIG; i++)
|
||||||
|
{
|
||||||
|
mListHandlers[i].clear();
|
||||||
|
signal(i, _sigHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixSignal::~UnixSignal(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < C_NSIG; i++)
|
||||||
|
{
|
||||||
|
mListHandlers[i].clear();
|
||||||
|
signal(i, SIG_DFL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixSignal::Register(sighandler_t handler, int sig) // register the handler to the signal
|
||||||
|
{
|
||||||
|
if (sig <= 0 || sig >= C_NSIG)
|
||||||
|
{
|
||||||
|
LOG(ERR) << "Unable to register callback for UnixSignal " << sig << " (out of range)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLock[sig].lock();
|
||||||
|
mListHandlers[sig].insert(mListHandlers[sig].end(), handler);
|
||||||
|
mLock[sig].unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixSignal::Dump(void)
|
||||||
|
{
|
||||||
|
for (int sig = 0; sig < C_NSIG; sig++)
|
||||||
|
{
|
||||||
|
mLock[sig].lock();
|
||||||
|
if (mListHandlers[sig].size() != 0)
|
||||||
|
{
|
||||||
|
printf("Signal vectors for signal %d: ", sig);
|
||||||
|
for (std::list<sighandler_t>::iterator i = mListHandlers[sig].begin();
|
||||||
|
i != mListHandlers[sig].end(); i++)
|
||||||
|
{
|
||||||
|
printf("%s0x%p", i == mListHandlers[sig].begin() ? "" : ", ", *i);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
mLock[sig].unlock();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UNIXSIGNAL_H
|
||||||
|
#define UNIXSIGNAL_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
/** A C++ wrapper for managing unix signals. */
|
||||||
|
class UnixSignal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int C_NSIG = 64;
|
||||||
|
private:
|
||||||
|
std::list<sighandler_t> mListHandlers[C_NSIG]; // list of signal handlers to call for all signals
|
||||||
|
Mutex mLock[C_NSIG];
|
||||||
|
public:
|
||||||
|
UnixSignal(void);
|
||||||
|
~UnixSignal(void);
|
||||||
|
|
||||||
|
void Register(sighandler_t handler, int sig); // register a signal handler with the system
|
||||||
|
void Handler(int sig); // main signal handler, iterates through mListHandlers
|
||||||
|
void Dump(void); // debug dump of list
|
||||||
|
};
|
||||||
|
|
||||||
|
extern UnixSignal gSigVec;
|
||||||
|
#endif // UNIXSIGNAL_H
|
||||||
|
// vim: ts=4 sw=4
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
* See the COPYING file in the main directory for details.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "UnixSignal.h"
|
||||||
|
#include "Configuration.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
ConfigurationTable gConfig;
|
||||||
|
|
||||||
|
void test1(int sig) { printf("Test 1, signal %d\n", sig); }
|
||||||
|
void test2(int sig) { printf("Test 2, signal %d\n", sig); }
|
||||||
|
void test3(int sig) { printf("Test 3, signal %d\n", sig); }
|
||||||
|
void test4(int sig) { printf("Test 4, signal %d\n", sig); }
|
||||||
|
void test5(int sig) { printf("Test 5, signal %d\n", sig); }
|
||||||
|
void test6(int sig) { printf("Test 6, signal %d\n", sig); }
|
||||||
|
|
||||||
|
void registerFuncs(int sig)
|
||||||
|
{
|
||||||
|
gSigVec.Register(test1, sig);
|
||||||
|
gSigVec.Register(test2, sig);
|
||||||
|
gSigVec.Register(test3, sig);
|
||||||
|
gSigVec.Register(test4, sig);
|
||||||
|
gSigVec.Register(test5, sig);
|
||||||
|
gSigVec.Register(test6, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
gLogInit("UnixSignalTest","DEBUG",LOG_LOCAL7);
|
||||||
|
registerFuncs(SIGINT);
|
||||||
|
registerFuncs(SIGHUP);
|
||||||
|
registerFuncs(SIGTERM);
|
||||||
|
printf("Test1 @ %p\n", test1);
|
||||||
|
printf("Test2 @ %p\n", test2);
|
||||||
|
printf("Test3 @ %p\n", test3);
|
||||||
|
printf("Test4 @ %p\n", test4);
|
||||||
|
printf("Test5 @ %p\n", test5);
|
||||||
|
printf("Test6 @ %p\n", test6);
|
||||||
|
printf("\n");
|
||||||
|
gSigVec.Dump();
|
||||||
|
|
||||||
|
printf("Run this three times. First time, do a 'kill %d' to test SIGTERM\n", getpid());
|
||||||
|
printf("Second time, do a 'kill -%d %d' to test SIGHUP\n", SIGHUP, getpid());
|
||||||
|
printf("Third time, do a Control-C to test SIGINT\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Output should iterate through tests 1-6 with the correct signal number\n");
|
||||||
|
printf("%d for SIGTERM, %d for SIGHUP, %d for SIGINT\n",
|
||||||
|
SIGTERM, SIGHUP, SIGINT);
|
||||||
|
while(true)
|
||||||
|
sleep(60);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This software is distributed under multiple licenses;
|
||||||
|
* see the COPYING file in the main directory for licensing
|
||||||
|
* information for this specific distribuion.
|
||||||
|
*
|
||||||
|
* This use of this software may be subject to additional restrictions.
|
||||||
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnixSignal.h"
|
||||||
|
#include "SelfDetect.h"
|
||||||
|
|
||||||
|
// These variables all have constructors, and their may be some interaction
|
||||||
|
// between them, so the order of construction is important.
|
||||||
|
UnixSignal gSigVec;
|
||||||
|
SelfDetect gSelf;
|
Loading…
Reference in New Issue