Implement a signalhandler via ACE.

Thanks to Diver for test compiling under WIN.

--HG--
branch : trunk
This commit is contained in:
Anubisss
2010-05-19 21:16:59 +02:00
parent a04809437b
commit a5840e9286
6 changed files with 124 additions and 101 deletions
+1
View File
@@ -16,6 +16,7 @@ SET(shared_STAT_SRCS
Log.h
ProgressBar.cpp
ProgressBar.h
SignalHandler.h
Threading.cpp
Timer.h
Util.cpp
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
*
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SIGNAL_HANDLER_H__
#define __SIGNAL_HANDLER_H__
#include <ace/Event_Handler.h>
namespace Trinity
{
/// Handle termination signals
class SignalHandler : public ACE_Event_Handler
{
public:
int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL)
{
HandleSignal(SigNum);
return 0;
}
virtual void HandleSignal(int SigNum) {};
};
}
#endif /* __SIGNAL_HANDLER_H__ */
+39 -47
View File
@@ -22,10 +22,11 @@
\ingroup Trinityd
*/
#include <ace/OS_NS_signal.h>
#include <ace/Sig_Handler.h>
#include "Common.h"
#include "SystemConfig.h"
#include "SignalHandler.h"
#include "World.h"
#include "WorldRunnable.h"
#include "WorldSocket.h"
@@ -60,6 +61,28 @@ INSTANTIATE_SINGLETON_1( Master );
volatile uint32 Master::m_masterLoopCounter = 0;
/// Handle cored's termination signals
class CoredSignalHandler : public Trinity::SignalHandler
{
public:
virtual void HandleSignal(int SigNum)
{
switch (SigNum)
{
case SIGINT:
World::StopNow(RESTART_EXIT_CODE);
break;
case SIGTERM:
#ifdef _WIN32
case SIGBREAK:
if (m_ServiceStatus != 1)
#endif /* _WIN32 */
World::StopNow(SHUTDOWN_EXIT_CODE);
break;
}
}
};
class FreezeDetectorRunnable : public ACE_Based::Runnable
{
public:
@@ -233,8 +256,21 @@ int Master::Run()
///- Initialize the World
sWorld.SetInitialWorldSettings();
///- Catch termination signals
_HookSignals();
// Initialise the signal handlers
CoredSignalHandler SignalINT, SignalTERM;
#ifdef _WIN32
CoredSignalHandler SignalBREAK;
#endif /* _WIN32 */
// Register realmd's signal handlers
ACE_Sig_Handler Handler;
Handler.register_handler(SIGINT, &SignalINT);
Handler.register_handler(SIGTERM, &SignalTERM);
#ifdef _WIN32
Handler.register_handler(SIGBREAK, &SignalBREAK);
#endif /* _WIN32 */
///- Launch WorldRunnable thread
ACE_Based::Thread world_thread(new WorldRunnable);
@@ -329,9 +365,6 @@ int Master::Run()
// set server offline
LoginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);
///- Remove signal handling before leaving
_UnhookSignals();
// when the main thread closes the singletons get unloaded
// since worldrunnable uses them, it will crash if unloaded after master
world_thread.wait();
@@ -507,44 +540,3 @@ void Master::clearOnlineAccounts()
// Battleground instance ids reset at server restart
CharacterDatabase.Execute("UPDATE character_battleground_data SET instance_id = 0");
}
/// Handle termination signals
void Master::_OnSignal(int s)
{
switch (s)
{
case SIGINT:
World::StopNow(RESTART_EXIT_CODE);
break;
case SIGTERM:
#ifdef _WIN32
case SIGBREAK:
if (m_ServiceStatus != 1)
#endif
World::StopNow(SHUTDOWN_EXIT_CODE);
break;
}
signal(s, _OnSignal);
}
/// Define hook '_OnSignal' for all termination signals
void Master::_HookSignals()
{
signal(SIGINT, _OnSignal);
signal(SIGTERM, _OnSignal);
#ifdef _WIN32
if (m_ServiceStatus != 1)
signal(SIGBREAK, _OnSignal);
#endif
}
/// Unhook the signals before leaving
void Master::_UnhookSignals()
{
signal(SIGINT, 0);
signal(SIGTERM, 0);
#ifdef _WIN32
signal(SIGBREAK, 0);
#endif
}
-4
View File
@@ -40,10 +40,6 @@ class Master
private:
bool _StartDB();
void _HookSignals();
void _UnhookSignals();
static void _OnSignal(int s);
void clearOnlineAccounts();
};
+37 -50
View File
@@ -29,11 +29,13 @@
#include "Log.h"
#include "SystemConfig.h"
#include "Util.h"
#include "SignalHandler.h"
#include "RealmList.h"
#include "RealmAcceptor.h"
#include <ace/Dev_Poll_Reactor.h>
#include <ace/ACE.h>
#include <ace/Sig_Handler.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
@@ -57,13 +59,33 @@ int m_ServiceStatus = -1;
#endif
bool StartDB();
void UnhookSignals();
void HookSignals();
bool stopEvent = false; ///< Setting it to true stops the server
DatabaseType LoginDatabase; ///< Accessor to the realm server database
/// Handle realmd's termination signals
class RealmdSignalHandler : public Trinity::SignalHandler
{
public:
virtual void HandleSignal(int SigNum)
{
switch (SigNum)
{
case SIGINT:
case SIGTERM:
stopEvent = true;
break;
#ifdef _WIN32
case SIGBREAK:
if (m_ServiceStatus != 1)
stopEvent = true;
break;
#endif /* _WIN32 */
}
}
};
/// Print out the usage string for this program on the console.
void usage(const char *prog)
{
@@ -214,8 +236,19 @@ extern int main(int argc, char **argv)
return 1;
}
///- Catch termination signals
HookSignals();
// Initialise the signal handlers
RealmdSignalHandler SignalINT, SignalTERM;
#ifdef _WIN32
RealmdSignalHandler SignalBREAK;
#endif /* _WIN32 */
// Register realmd's signal handlers
ACE_Sig_Handler Handler;
Handler.register_handler(SIGINT, &SignalINT);
Handler.register_handler(SIGTERM, &SignalTERM);
#ifdef _WIN32
Handler.register_handler(SIGBREAK, &SignalBREAK);
#endif /* _WIN32 */();
///- Handle affinity for multiple processors and process priority on Windows
#ifdef WIN32
@@ -303,34 +336,10 @@ extern int main(int argc, char **argv)
LoginDatabase.ThreadEnd();
LoginDatabase.HaltDelayThread();
///- Remove signal handling before leaving
UnhookSignals();
sLog.outString("Halting process...");
return 0;
}
/// Handle termination signals
/** Put the global variable stopEvent to 'true' if a termination signal is caught **/
void OnSignal(int s)
{
switch (s)
{
case SIGINT:
case SIGTERM:
stopEvent = true;
break;
#ifdef _WIN32
case SIGBREAK:
if (m_ServiceStatus != 1)
stopEvent = true;
break;
#endif
}
signal(s, OnSignal);
}
/// Initialize connection to the database
bool StartDB()
{
@@ -351,26 +360,4 @@ bool StartDB()
return true;
}
/// Define hook 'OnSignal' for all termination signals
void HookSignals()
{
signal(SIGINT, OnSignal);
signal(SIGTERM, OnSignal);
#ifdef _WIN32
if (m_ServiceStatus != 1)
signal(SIGBREAK, OnSignal);
#endif
}
/// Unhook the signals before leaving
void UnhookSignals()
{
signal(SIGINT, 0);
signal(SIGTERM, 0);
#ifdef _WIN32
if (m_ServiceStatus != 1)
signal(SIGBREAK, 0);
#endif
}
/// @}