From 5c0eb60b509edf766e649d081d30ab8dea83a8f4 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sun, 22 Feb 2009 06:16:10 +0000 Subject: added signal controller (console control handler) to windows --- src/anytun-controld.cpp | 7 ++-- src/anytun.cpp | 5 +-- src/anytun.suo | Bin 64000 -> 66048 bytes src/anytun.vcproj | 12 +++++- src/signalController.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++---- src/signalController.h | 77 +++++++++++++++++++++++++++++++++++-- src/win32/winService.cpp | 12 +++--- 7 files changed, 185 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/anytun-controld.cpp b/src/anytun-controld.cpp index 680d143..2c6c619 100644 --- a/src/anytun-controld.cpp +++ b/src/anytun-controld.cpp @@ -150,14 +150,13 @@ int main(int argc, char* argv[]) pidFile << pid; pidFile.close(); } - - SignalController sig; - sig.init(); + + gSignalController.init(); boost::thread * syncListenerThread; syncListenerThread = new boost::thread(boost::bind(syncListener)); - int ret = sig.run(); + int ret = gSignalController.run(); return ret; } diff --git a/src/anytun.cpp b/src/anytun.cpp index 1fb1fd8..b6f370b 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -476,8 +476,7 @@ int main(int argc, char* argv[]) #endif #ifndef NO_SIGNALCONTROLLER - SignalController sig; - sig.init(); + gSignalController.init(); #endif OptionHost* connTo = new OptionHost(); @@ -503,7 +502,7 @@ int main(int argc, char* argv[]) int ret = 0; gWinService.waitForStop(); #elif !defined(NO_SIGNALCONTROLLER) - int ret = sig.run(); + int ret = gSignalController.run(); #else receiver(&p); int ret = 0; diff --git a/src/anytun.suo b/src/anytun.suo index 05fc354..2392b5f 100644 Binary files a/src/anytun.suo and b/src/anytun.suo differ diff --git a/src/anytun.vcproj b/src/anytun.vcproj index 16cb37f..696e905 100644 --- a/src/anytun.vcproj +++ b/src/anytun.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" AdditionalOptions="/I "C:\Program Files\boost\boost_1_35_0\"" Optimization="0" - PreprocessorDefinitions="LOG_FILE;LOG_STDOUT;LOG_WINEVENTLOG;USE_SSL_CRYPTO;NO_DAEMON;NO_EXEC;NO_SIGNALCONTROLLER;WIN32_LEAN_AND_MEAN" + PreprocessorDefinitions="LOG_FILE;LOG_STDOUT;LOG_WINEVENTLOG;USE_SSL_CRYPTO;NO_DAEMON;NO_EXEC;WIN32_LEAN_AND_MEAN" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -116,7 +116,7 @@ /> + + @@ -616,6 +620,10 @@ RelativePath=".\seqWindow.cpp" > + + diff --git a/src/signalController.cpp b/src/signalController.cpp index 8d9c78f..4868d55 100644 --- a/src/signalController.cpp +++ b/src/signalController.cpp @@ -29,16 +29,37 @@ * along with anytun. If not, see . */ -#include -#include +#ifndef NO_SIGNALCONTROLLER +#include #include -#include -#include "threadUtils.hpp" #include "signalController.h" #include "log.h" +#include "threadUtils.hpp" +#ifndef _MSC_VER +#include +#include +#else +#include +#endif + +SignalController* SignalController::inst = NULL; +Mutex SignalController::instMutex; +SignalController& gSignalController = SignalController::instance(); + +SignalController& SignalController::instance() +{ + Lock lock(instMutex); + static instanceCleaner c; + if(!inst) + inst = new SignalController(); + + return *inst; +} + +#ifndef _MSC_VER int SigIntHandler::handle() { @@ -81,14 +102,54 @@ int SigUsr2Handler::handle() return 0; } +#else +int CtrlCHandler::handle() +{ + cLog.msg(Log::PRIO_NOTICE) << "CTRL-C Event received, exitting"; + + return 1; +} + +int CtrlBreakHandler::handle() +{ + cLog.msg(Log::PRIO_NOTICE) << "CTRL-Break Event received, ignoring"; + + return 0; +} + +int CtrlCloseHandler::handle() +{ + cLog.msg(Log::PRIO_NOTICE) << "Close Event received, exitting"; + + return 1; +} + +int CtrlLogoffHandler::handle() +{ + cLog.msg(Log::PRIO_NOTICE) << "LogOff Event received, exitting"; + + return 1; +} + +int CtrlShutdownHandler::handle() +{ + cLog.msg(Log::PRIO_NOTICE) << "Shutdown Event received, exitting"; + + return 1; +} +#endif SignalController::~SignalController() { for(HandlerMap::iterator it = handler.begin(); it != handler.end(); ++it) delete it->second; + +#ifndef _MSC_VER if(thread) delete thread; +#endif } +#ifndef _MSC_VER void SignalController::handle(void *s) { SignalController* self = reinterpret_cast(s); @@ -106,9 +167,18 @@ void SignalController::handle(void *s) self->sigQueueSem.up(); } } +#else +bool SignalController::handle(DWORD ctrlType) +{ + gSignalController.sigQueue.push(ctrlType); + gSignalController.sigQueueSem.up(); + return true; +} +#endif void SignalController::init() { +#ifndef _MSC_VER sigset_t signal_set; sigfillset(&signal_set); @@ -122,7 +192,7 @@ void SignalController::init() #else #error The signalhandler works only with pthreads #endif - + thread = new boost::thread(boost::bind(handle, this)); handler[SIGINT] = new SigIntHandler; @@ -131,12 +201,24 @@ void SignalController::init() handler[SIGTERM] = new SigTermHandler; handler[SIGUSR1] = new SigUsr1Handler; handler[SIGUSR2] = new SigUsr2Handler; +#else + if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalController::handle, true)) { + std::stringstream msg; + msg << "Error on SetConsoleCtrlhandler: " << LogErrno(GetLastError()); + throw std::runtime_error(msg.str()); + } + + handler[CTRL_C_EVENT] = new CtrlCHandler; + handler[CTRL_BREAK_EVENT] = new CtrlBreakHandler; + handler[CTRL_CLOSE_EVENT] = new CtrlCloseHandler; + handler[CTRL_LOGOFF_EVENT] = new CtrlLogoffHandler; + handler[CTRL_SHUTDOWN_EVENT] = new CtrlShutdownHandler; +#endif } int SignalController::run() { - while(1) - { + while(1) { sigQueueSem.down(); int sigNum; { @@ -157,3 +239,5 @@ int SignalController::run() } return 0; } + +#endif \ No newline at end of file diff --git a/src/signalController.h b/src/signalController.h index d99e168..c893e15 100644 --- a/src/signalController.h +++ b/src/signalController.h @@ -32,12 +32,17 @@ #ifndef _SIGNAL_CONTROLLER_H_ #define _SIGNAL_CONTROLLER_H_ -#include +#ifndef NO_SIGNALCONTROLLER + #include #include #include "threadUtils.hpp" +#ifndef _MSC_VER +#include +#endif + class SignalHandler { public: @@ -53,6 +58,7 @@ private: friend class SignalController; }; +#ifndef _MSC_VER class SigIntHandler : public SignalHandler { public: @@ -95,12 +101,53 @@ public: int handle(); }; +#else + +class CtrlCHandler : public SignalHandler +{ +public: + CtrlCHandler() : SignalHandler(CTRL_C_EVENT) {} + int handle(); +}; + +class CtrlBreakHandler : public SignalHandler +{ +public: + CtrlBreakHandler() : SignalHandler(CTRL_BREAK_EVENT) {} + int handle(); +}; + +class CtrlCloseHandler : public SignalHandler +{ +public: + CtrlCloseHandler() : SignalHandler(CTRL_BREAK_EVENT) {} + int handle(); +}; + +class CtrlLogoffHandler : public SignalHandler +{ +public: + CtrlLogoffHandler() : SignalHandler(CTRL_BREAK_EVENT) {} + int handle(); +}; + +class CtrlShutdownHandler : public SignalHandler +{ +public: + CtrlShutdownHandler() : SignalHandler(CTRL_BREAK_EVENT) {} + int handle(); +}; +#endif + class SignalController { public: - SignalController() { thread = NULL; } - ~SignalController(); + static SignalController& instance(); +#ifndef _MSC_VER static void handle(void* s); +#else + static bool handle(DWORD ctrlType); +#endif void init(); int run(); @@ -108,15 +155,37 @@ public: private: typedef std::map HandlerMap; +#ifndef _MSC_VER + SignalController() : thread(null) {}; +#else + SignalController() {}; +#endif + ~SignalController(); SignalController(const SignalController &s); void operator=(const SignalController &s); - + + static SignalController* inst; + static Mutex instMutex; + class instanceCleaner { + public: ~instanceCleaner() { + if(SignalController::inst != NULL) + delete SignalController::inst; + } + }; + friend class instanceCleaner; + std::queue sigQueue; Mutex sigQueueMutex; Semaphore sigQueueSem; +#ifdef _MSC_VER boost::thread* thread; +#endif HandlerMap handler; }; +extern SignalController& gSignalController; + +#endif + #endif diff --git a/src/win32/winService.cpp b/src/win32/winService.cpp index 78558de..fb20f8f 100644 --- a/src/win32/winService.cpp +++ b/src/win32/winService.cpp @@ -145,7 +145,8 @@ void WinService::waitForStop() { if(!started_) throw std::runtime_error("Service not started correctly"); - + + reportStatus(SERVICE_RUNNING, NO_ERROR); WaitForSingleObject(stop_event_, INFINITE); reportStatus(SERVICE_STOP_PENDING, NO_ERROR); } @@ -175,16 +176,15 @@ VOID WINAPI WinService::main(DWORD dwArgc, LPTSTR *lpszArgv) gWinService.status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS; gWinService.status_.dwServiceSpecificExitCode = 0; gWinService.reportStatus(SERVICE_START_PENDING, NO_ERROR); - + gWinService.started_ = true; + gWinService.stop_event_ = CreateEvent(NULL, true, false, NULL); if(!gWinService.stop_event_) { - cLog.msg(Log::PRIO_ERR) << "Error on CreateEvent: " << LogErrno(GetLastError()); + cLog.msg(Log::PRIO_ERR) << "WinService Error on CreateEvent: " << LogErrno(GetLastError()); gWinService.reportStatus(SERVICE_STOPPED, -1); return; } - gWinService.started_ = true; - gWinService.reportStatus(SERVICE_RUNNING, NO_ERROR); - + real_main(dwArgc, lpszArgv); } -- cgit v1.2.3