diff options
| -rw-r--r-- | indra/llcommon/llerror.cpp | 97 | ||||
| -rw-r--r-- | indra/llcommon/llevents.cpp | 12 | ||||
| -rw-r--r-- | indra/llcommon/llevents.h | 18 | ||||
| -rw-r--r-- | indra/llcommon/llhandle.h | 1 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 8 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 9 | ||||
| -rw-r--r-- | indra/viewer_components/updater/llupdaterservice.cpp | 10 | 
7 files changed, 105 insertions, 50 deletions
| diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e6407ecf22..2ddb3edbdd 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1067,7 +1067,15 @@ namespace LLError  		{  			return false;  		} -		 + +		// If we hit a logging request very late during shutdown processing, +		// when either of the relevant LLSingletons has already been deleted, +		// DO NOT resurrect them. +		if (Settings::wasDeleted() || Globals::wasDeleted()) +		{ +			return false; +		} +  		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();  		s->mShouldLogCallCounter++; @@ -1106,7 +1114,10 @@ namespace LLError  	std::ostringstream* Log::out()  	{  		LogLock lock; -		if (lock.ok()) +		// If we hit a logging request very late during shutdown processing, +		// when either of the relevant LLSingletons has already been deleted, +		// DO NOT resurrect them. +		if (lock.ok() && ! (Settings::wasDeleted() || Globals::wasDeleted()))  		{  			Globals* g = Globals::getInstance(); @@ -1116,41 +1127,49 @@ namespace LLError  				return &g->messageStream;  			}  		} -		 +  		return new std::ostringstream;  	} -	 +  	void Log::flush(std::ostringstream* out, char* message) -    { -       LogLock lock; -       if (!lock.ok()) -       { -           return; -       } -        -	   if(strlen(out->str().c_str()) < 128) -	   { -		   strcpy(message, out->str().c_str()); -	   } -	   else -	   { -		   strncpy(message, out->str().c_str(), 127); -		   message[127] = '\0' ; -	   } -	    -	   Globals* g = Globals::getInstance(); -       if (out == &g->messageStream) -       { -           g->messageStream.clear(); -           g->messageStream.str(""); -           g->messageStreamInUse = false; -       } -       else -       { -           delete out; -       } -	   return ; -    } +	{ +		LogLock lock; +		if (!lock.ok()) +		{ +			return; +		} + +		// If we hit a logging request very late during shutdown processing, +		// when either of the relevant LLSingletons has already been deleted, +		// DO NOT resurrect them. +		if (Settings::wasDeleted() || Globals::wasDeleted()) +		{ +			return; +		} + +		if(strlen(out->str().c_str()) < 128) +		{ +			strcpy(message, out->str().c_str()); +		} +		else +		{ +			strncpy(message, out->str().c_str(), 127); +			message[127] = '\0' ; +		} + +		Globals* g = Globals::getInstance(); +		if (out == &g->messageStream) +		{ +			g->messageStream.clear(); +			g->messageStream.str(""); +			g->messageStreamInUse = false; +		} +		else +		{ +			delete out; +		} +		return ; +	}  	void Log::flush(std::ostringstream* out, const CallSite& site)  	{ @@ -1159,7 +1178,15 @@ namespace LLError  		{  			return;  		} -		 + +		// If we hit a logging request very late during shutdown processing, +		// when either of the relevant LLSingletons has already been deleted, +		// DO NOT resurrect them. +		if (Settings::wasDeleted() || Globals::wasDeleted()) +		{ +			return; +		} +  		Globals* g = Globals::getInstance();  		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 97270e4931..a3856e4fc4 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -281,7 +281,8 @@ const std::string LLEventPump::ANONYMOUS = std::string();  LLEventPump::LLEventPump(const std::string& name, bool tweak):      // Register every new instance with LLEventPumps -    mName(LLEventPumps::instance().registerNew(*this, name, tweak)), +    mRegistry(LLEventPumps::instance().getHandle()), +    mName(mRegistry.get()->registerNew(*this, name, tweak)),      mSignal(new LLStandardSignal()),      mEnabled(true)  {} @@ -292,8 +293,13 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):  LLEventPump::~LLEventPump()  { -    // Unregister this doomed instance from LLEventPumps -    LLEventPumps::instance().unregister(*this); +    // Unregister this doomed instance from LLEventPumps -- but only if +    // LLEventPumps is still around! +    LLEventPumps* registry = mRegistry.get(); +    if (registry) +    { +        registry->unregister(*this); +    }  }  // static data member diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 7cff7dfd45..1d51c660ed 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -62,6 +62,7 @@  #include "lldependencies.h"  #include "llstl.h"  #include "llexception.h" +#include "llhandle.h"  /*==========================================================================*|  // override this to allow binding free functions with more parameters @@ -227,7 +228,15 @@ class LLEventPump;   * LLEventPumps is a Singleton manager through which one typically accesses   * this subsystem.   */ -class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps> +// LLEventPumps isa LLHandleProvider only for (hopefully rare) long-lived +// class objects that must refer to this class late in their lifespan, say in +// the destructor. Specifically, the case that matters is a possible reference +// after LLEventPumps::deleteSingleton(). (Lingering LLEventPump instances are +// capable of this.) In that case, instead of calling LLEventPumps::instance() +// again -- resurrecting the deleted LLSingleton -- store an +// LLHandle<LLEventPumps> and test it before use. +class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>, +                                  public LLHandleProvider<LLEventPumps>  {      LLSINGLETON(LLEventPumps);  public: @@ -590,6 +599,9 @@ private:          return this->listen_impl(name, listener, after, before);      } +    // must precede mName; see LLEventPump::LLEventPump() +    LLHandle<LLEventPumps> mRegistry; +      std::string mName;  protected: @@ -817,14 +829,14 @@ public:          mConnection(new LLBoundListener)      {      } -	 +      /// Copy constructor. Copy shared_ptrs to original instance data.      LLListenerWrapperBase(const LLListenerWrapperBase& that):          mName(that.mName),          mConnection(that.mConnection)      {      } -	virtual ~LLListenerWrapperBase() {} +    virtual ~LLListenerWrapperBase() {}      /// Ask LLEventPump::listen() for the listener name      virtual void accept_name(const std::string& name) const diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h index feb5f41848..570cd330b8 100644 --- a/indra/llcommon/llhandle.h +++ b/indra/llcommon/llhandle.h @@ -28,6 +28,7 @@  #define LLHANDLE_H  #include "llpointer.h" +#include "llrefcount.h"  #include "llexception.h"  #include <stdexcept>  #include <boost/type_traits/is_convertible.hpp> diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 1b915dfd6e..0d4a1f34f8 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -452,6 +452,14 @@ public:          return sData.mInitState == INITIALIZED;      } +    // Has this singleton been deleted? This can be useful during shutdown +    // processing to avoid "resurrecting" a singleton we thought we'd already +    // cleaned up. +    static bool wasDeleted() +    { +        return sData.mInitState == DELETED; +    } +  private:      struct SingletonData      { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ff54977634..204a19da7f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -738,10 +738,7 @@ LLAppViewer::LLAppViewer()  LLAppViewer::~LLAppViewer()  {  	delete mSettingsLocationList; -	LLViewerEventRecorder::deleteSingleton(); -	LLLoginInstance::instance().setUpdaterService(0); -	  	destroyMainloopTimeout();  	// If we got to this destructor somehow, the app didn't hang. @@ -2110,6 +2107,10 @@ bool LLAppViewer::cleanup()  	// realtime, or might throw an exception.  	LLSingletonBase::cleanupAll(); +	// The logging subsystem depends on an LLSingleton. Any logging after +	// LLSingletonBase::deleteAll() won't be recorded. +	LL_INFOS() << "Goodbye!" << LL_ENDL; +  	// This calls every remaining LLSingleton's deleteSingleton() method.  	// No class destructor should perform any cleanup that might take  	// significant realtime, or throw an exception. @@ -2122,8 +2123,6 @@ bool LLAppViewer::cleanup()  	// probably useful to be able to log that order.  	LLSingletonBase::deleteAll(); -	LL_INFOS() << "Goodbye!" << LL_ENDL; -  	removeDumpDir();  	// return 0; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1665e41e70..df021948c3 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -158,7 +158,8 @@ public:  private:  	std::string mNewChannel;  	std::string mNewVersion; -	 +	LLTempBoundListener mMainLoopConnection; +  	void restartTimer(unsigned int seconds);  	void setState(LLUpdaterService::eUpdaterState state);  	void stopTimer(); @@ -179,7 +180,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() :  LLUpdaterServiceImpl::~LLUpdaterServiceImpl()  {  	LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL; -	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); +	// Destroying an LLTempBoundListener implicitly disconnects. That's its +	// whole purpose.  }  void LLUpdaterServiceImpl::initialize(const std::string&  channel, @@ -560,7 +562,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)  	seconds << " seconds" << LL_ENDL;   	mTimer.start();  	mTimer.setTimerExpirySec((F32)seconds); -	LLEventPumps::instance().obtain("mainloop").listen( +	mMainLoopConnection = LLEventPumps::instance().obtain("mainloop").listen(  		sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));  } @@ -589,7 +591,7 @@ void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state)  void LLUpdaterServiceImpl::stopTimer()  {  	mTimer.stop(); -	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); +	mMainLoopConnection.disconnect();  }  bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) | 
