From: <ps...@us...> - 2009-09-10 18:28:05
|
Revision: 1624 http://znc.svn.sourceforge.net/znc/?rev=1624&view=rev Author: psychon Date: 2009-09-10 18:27:56 +0000 (Thu, 10 Sep 2009) Log Message: ----------- Fix a theoretical crash on shutdown CZNC::~CZNC() set its pointer to the CConnectUserTimer to NULL and then called the manager's Cleanup(). If some destructor that is called from here then calls EnableConnectUser(), a new CConnectUserTimer is created and its address is saved. But since the manager is destroying all timers, this pointer will soon become dangling and might crash us later on. This is solved by clearing CZNC's pointer in CConnectUserTimer's destructor. Modified Paths: -------------- trunk/znc.cpp trunk/znc.h Modified: trunk/znc.cpp =================================================================== --- trunk/znc.cpp 2009-09-10 10:50:48 UTC (rev 1623) +++ trunk/znc.cpp 2009-09-10 18:27:56 UTC (rev 1624) @@ -1794,7 +1794,18 @@ // Don't wait iSecs seconds for first timer run m_bRunOnNextCall = true; } - virtual ~CConnectUserTimer() {} + virtual ~CConnectUserTimer() { + // This is only needed when ZNC shuts down: + // CZNC::~CZNC() sets its CConnectUserTimer pointer to NULL and + // calls the manager's Cleanup() which destroys all sockets and + // timers. If something calls CZNC::EnableConnectUser() here + // (e.g. because a CIRCSock is destroyed), the socket manager + // deletes that timer almost immediately, but CZNC now got a + // dangling pointer to this timer which can crash later on. + // + // Unlikely but possible ;) + CZNC::Get().LeakConnectUser(this); + } protected: virtual void RunJob() { @@ -1870,3 +1881,8 @@ m_pConnectUserTimer->Stop(); m_pConnectUserTimer = NULL; } + +void CZNC::LeakConnectUser(CConnectUserTimer *pTimer) { + if (m_pConnectUserTimer == pTimer) + m_pConnectUserTimer = NULL; +} Modified: trunk/znc.h =================================================================== --- trunk/znc.h 2009-09-10 10:50:48 UTC (rev 1623) +++ trunk/znc.h 2009-09-10 18:27:56 UTC (rev 1624) @@ -125,6 +125,9 @@ void EnableConnectUser(); void DisableConnectUser(); + // Never call this unless you are CConnectUserTimer::~CConnectUserTimer() + void LeakConnectUser(CConnectUserTimer *pTimer); + private: bool DoRehash(CString& sError); // Returns true if something was done This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |