From 5659db6f03dfbb081608f6d202e62d29d239f4ea Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 11 Apr 2015 01:55:45 +0200 Subject: Core/Bnet: Fixed crash on shutdown happening when there were still players connected --- src/server/bnetserver/Main.cpp | 31 +++++++++++++++++---------- src/server/bnetserver/Realms/RealmList.cpp | 1 + src/server/bnetserver/Server/SessionManager.h | 2 +- src/server/shared/Networking/AsyncAcceptor.h | 18 +++++++++++++--- src/server/shared/Networking/NetworkThread.h | 2 ++ src/server/shared/Networking/SocketMgr.h | 11 ++++++++-- 6 files changed, 48 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 678e24c4682..6299ae802a7 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -57,8 +57,8 @@ void SignalHandler(const boost::system::error_code& error, int signalNumber); void KeepDatabaseAliveHandler(const boost::system::error_code& error); variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile); -boost::asio::io_service _ioService; -boost::asio::deadline_timer _dbPingTimer(_ioService); +std::unique_ptr _ioService; +std::unique_ptr _dbPingTimer; uint32 _dbPingInterval; LoginDatabaseWorkerPool LoginDatabase; @@ -109,8 +109,10 @@ int main(int argc, char** argv) sIpcContext->Initialize(); + _ioService.reset(new boost::asio::io_service()); + // Get the list of realms for the server - sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10), worldListenPort); + sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10), worldListenPort); // Start the listening port (acceptor) for auth connections int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); @@ -123,10 +125,10 @@ int main(int argc, char** argv) std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); - sSessionMgr.StartNetwork(_ioService, bindIp, bnport); + sSessionMgr.StartNetwork(*_ioService, bindIp, bnport); // Set signal handlers - boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); + boost::asio::signal_set signals(*_ioService, SIGINT, SIGTERM); #if PLATFORM == PLATFORM_WINDOWS signals.add(SIGBREAK); #endif @@ -137,14 +139,19 @@ int main(int argc, char** argv) // Enabled a timed callback for handling the database keep alive ping _dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30); - _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); - _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + _dbPingTimer.reset(new boost::asio::deadline_timer(*_ioService)); + _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer->async_wait(KeepDatabaseAliveHandler); sComponentMgr->Load(); sModuleMgr->Load(); // Start the io service worker loop - _ioService.run(); + _ioService->run(); + + _dbPingTimer->cancel(); + + sSessionMgr.StopNetwork(); sIpcContext->Close(); @@ -153,6 +160,8 @@ int main(int argc, char** argv) // Close the Database Pool and library StopDB(); + _ioService.reset(); + TC_LOG_INFO("server.bnetserver", "Halting process..."); return 0; } @@ -186,7 +195,7 @@ void StopDB() void SignalHandler(const boost::system::error_code& error, int /*signalNumber*/) { if (!error) - _ioService.stop(); + _ioService->stop(); } void KeepDatabaseAliveHandler(const boost::system::error_code& error) @@ -196,8 +205,8 @@ void KeepDatabaseAliveHandler(const boost::system::error_code& error) TC_LOG_INFO("server.bnetserver", "Ping MySQL to keep connection alive"); LoginDatabase.KeepAlive(); - _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); - _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer->async_wait(KeepDatabaseAliveHandler); } } diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp index 0f1a2df807e..fe4bfe3425e 100644 --- a/src/server/bnetserver/Realms/RealmList.cpp +++ b/src/server/bnetserver/Realms/RealmList.cpp @@ -52,6 +52,7 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte void RealmList::Close() { _worldListener->End(); + _updateTimer->cancel(); } template diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h index 5f95616bf74..3ede9eb0ff6 100644 --- a/src/server/bnetserver/Server/SessionManager.h +++ b/src/server/bnetserver/Server/SessionManager.h @@ -40,7 +40,7 @@ namespace Battlenet #pragma pack(pop) - class SessionManager : SocketMgr + class SessionManager : public SocketMgr { typedef SocketMgr BaseSocketMgr; typedef std::map SessionMap; diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index d22d553965b..2c50a38dd59 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -30,7 +30,7 @@ public: AsyncAcceptor(boost::asio::io_service& ioService, std::string const& bindIp, uint16 port) : _acceptor(ioService, tcp::endpoint(boost::asio::ip::address::from_string(bindIp), port)), - _socket(ioService) + _socket(ioService), _closed(false) { } @@ -55,13 +55,24 @@ public: } } - AsyncAcceptManaged(mgrHandler); + if (!_closed) + AsyncAcceptManaged(mgrHandler); }); } + void Close() + { + if (_closed.exchange(true)) + return; + + boost::system::error_code err; + _acceptor.close(err); + } + private: tcp::acceptor _acceptor; tcp::socket _socket; + std::atomic _closed; }; template @@ -83,7 +94,8 @@ void AsyncAcceptor::AsyncAccept() } // lets slap some more this-> on this so we can fix this bug with gcc 4.7.2 throwing internals in yo face - this->AsyncAccept(); + if (!_closed) + this->AsyncAccept(); }); } diff --git a/src/server/shared/Networking/NetworkThread.h b/src/server/shared/Networking/NetworkThread.h index 05ca99ea6a6..219bcb07fbb 100644 --- a/src/server/shared/Networking/NetworkThread.h +++ b/src/server/shared/Networking/NetworkThread.h @@ -147,6 +147,8 @@ protected: } TC_LOG_DEBUG("misc", "Network Thread exits"); + _newSockets.clear(); + _Sockets.clear(); } private: diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h index e18a2077288..c7689ec8395 100644 --- a/src/server/shared/Networking/SocketMgr.h +++ b/src/server/shared/Networking/SocketMgr.h @@ -33,8 +33,7 @@ class SocketMgr public: virtual ~SocketMgr() { - delete _acceptor; - delete[] _threads; + ASSERT(!_threads && !_acceptor && !_threadCount, "StopNetwork must be called prior to SocketMgr destruction"); } virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) @@ -69,11 +68,19 @@ public: virtual void StopNetwork() { + _acceptor->Close(); + if (_threadCount != 0) for (int32 i = 0; i < _threadCount; ++i) _threads[i].Stop(); Wait(); + + delete _acceptor; + _acceptor = nullptr; + delete[] _threads; + _threads = nullptr; + _threadCount = 0; } void Wait() -- cgit v1.2.3