diff options
| author | Stinson Linden <stinson@lindenlab.com> | 2014-06-02 22:32:16 +0100 | 
|---|---|---|
| committer | Stinson Linden <stinson@lindenlab.com> | 2014-06-02 22:32:16 +0100 | 
| commit | 8392fde6f6a4dfdb2a78382f3587ecd5a6d937ff (patch) | |
| tree | 5c0b89998c072175cd1d1cb3c429a127af8f04d6 /indra/llcommon | |
| parent | 4885c122eaf1b4e304ce598f308d806322efacfc (diff) | |
| parent | 51e0cc8140a2cbe92363cb902144ccc9bf34b7c7 (diff) | |
Pull and merge from ssh://hg@bitbucket.org/lindenlab/viewer-drtvwr-365.
Diffstat (limited to 'indra/llcommon')
| -rwxr-xr-x | indra/llcommon/llerror.cpp | 444 | ||||
| -rwxr-xr-x | indra/llcommon/llerror.h | 4 | ||||
| -rwxr-xr-x | indra/llcommon/llerrorcontrol.h | 23 | ||||
| -rwxr-xr-x | indra/llcommon/llinitparam.h | 3 | ||||
| -rwxr-xr-x | indra/llcommon/tests/llerror_test.cpp | 78 | ||||
| -rwxr-xr-x | indra/llcommon/tests/wrapllerrs.h | 117 | 
6 files changed, 354 insertions, 315 deletions
| diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index a7963174ad..22cd861c72 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -47,6 +47,7 @@  #include "lllivefile.h"  #include "llsd.h"  #include "llsdserialize.h" +#include "llsingleton.h"  #include "llstl.h"  #include "lltimer.h" @@ -356,30 +357,31 @@ namespace  	typedef std::map<std::string, LLError::ELevel> LevelMap; -	typedef std::vector<LLError::Recorder*> Recorders; +	typedef std::vector<LLError::RecorderPtr> Recorders;  	typedef std::vector<LLError::CallSite*> CallSiteVector; -	class Globals +	class Globals : public LLSingleton<Globals>  	{  	public: +		Globals(); +  		std::ostringstream messageStream;  		bool messageStreamInUse;  		void addCallSite(LLError::CallSite&);  		void invalidateCallSites(); -		 -		static Globals& get(); -			// return the one instance of the globals  	private:  		CallSiteVector callSites; - -		Globals() -			:	messageStreamInUse(false) -			{ } -		  	}; +	Globals::Globals() +		: messageStream(), +		messageStreamInUse(false), +		callSites() +	{ +	} +  	void Globals::addCallSite(LLError::CallSite& site)  	{  		callSites.push_back(&site); @@ -396,25 +398,17 @@ namespace  		callSites.clear();  	} - -	Globals& Globals::get() -	{ -		/* This pattern, of returning a reference to a static function -		   variable, is to ensure that this global is constructed before -		   it is used, no matter what the global initialization sequence -		   is. -		   See C++ FAQ Lite, sections 10.12 through 10.14 -		*/ -		static Globals* globals = new Globals;		 -		return *globals; -	}  }  namespace LLError  { -	class Settings +	class SettingsConfig : public LLRefCount  	{ +		friend class Settings; +  	public: +		virtual ~SettingsConfig(); +  		bool                                mPrintLocation;  		LLError::ELevel                     mDefaultLevel; @@ -429,81 +423,86 @@ namespace LLError  		LLError::TimeFunction               mTimeFunction;  		Recorders                           mRecorders; -		Recorder*                           mFileRecorder; -		Recorder*                           mFixedBufferRecorder; +		RecorderPtr                         mFileRecorder; +		RecorderPtr                         mFixedBufferRecorder;  		std::string                         mFileRecorderFileName;  		int									mShouldLogCallCounter; -		static Settings& get(); +	private: +		SettingsConfig(); +	}; + +	typedef LLPointer<SettingsConfig> SettingsConfigPtr; + +	class Settings : public LLSingleton<Settings> +	{ +	public: +		Settings(); + +		SettingsConfigPtr getSettingsConfig(); -		static void reset(); -		static Settings* saveAndReset(); -		static void restore(Settings*); +		void reset(); +		SettingsStoragePtr saveAndReset(); +		void restore(SettingsStoragePtr pSettingsStorage);  	private: -		Settings() -		:	mPrintLocation(false), -			mDefaultLevel(LLError::LEVEL_DEBUG), -			mCrashFunction(), -			mTimeFunction(NULL), -			mFileRecorder(NULL), -			mFixedBufferRecorder(NULL), -			mShouldLogCallCounter(0) -			{ } -		 -		~Settings() -		{ -			for_each(mRecorders.begin(), mRecorders.end(), DeletePointer()); -			mRecorders.clear(); -		} -		 -		static Settings*& getPtr(); +		SettingsConfigPtr mSettingsConfig;  	}; -	Settings& Settings::get() +	SettingsConfig::SettingsConfig() +		: LLRefCount(), +		mPrintLocation(false), +		mDefaultLevel(LLError::LEVEL_DEBUG), +		mFunctionLevelMap(), +		mClassLevelMap(), +		mFileLevelMap(), +		mTagLevelMap(), +		mUniqueLogMessages(), +		mCrashFunction(NULL), +		mTimeFunction(NULL), +		mRecorders(), +		mFileRecorder(), +		mFixedBufferRecorder(), +		mFileRecorderFileName(), +		mShouldLogCallCounter(0)  	{ -		Settings* p = getPtr(); -		if (!p) -		{ -			reset(); -			p = getPtr(); -		} -		return *p;  	} -	 -	void Settings::reset() + +	SettingsConfig::~SettingsConfig()  	{ -		Globals::get().invalidateCallSites(); -		 -		Settings*& p = getPtr(); -		delete p; -		p = new Settings(); +		mRecorders.clear(); +	} + +	Settings::Settings() +		: LLSingleton<Settings>(), +		mSettingsConfig(new SettingsConfig()) +	{ +	} + +	SettingsConfigPtr Settings::getSettingsConfig() +	{ +		return mSettingsConfig;  	} -	Settings* Settings::saveAndReset() +	void Settings::reset()  	{ -		Globals::get().invalidateCallSites(); -		 -		Settings*& p = getPtr(); -		Settings* originalSettings = p; -		p = new Settings(); -		return originalSettings; +		Globals::getInstance()->invalidateCallSites(); +		mSettingsConfig = new SettingsConfig();  	} -	void Settings::restore(Settings* originalSettings) +	SettingsStoragePtr Settings::saveAndReset()  	{ -		Globals::get().invalidateCallSites(); -		 -		Settings*& p = getPtr(); -		delete p; -		p = originalSettings; +		SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); +		reset(); +		return oldSettingsConfig;  	} -	Settings*& Settings::getPtr() +	void Settings::restore(SettingsStoragePtr pSettingsStorage)  	{ -		static Settings* currentSettings = NULL; -		return currentSettings; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); +		mSettingsConfig = newSettingsConfig;  	}  } @@ -604,7 +603,7 @@ namespace  	void commonInit(const std::string& dir, bool log_to_stderr = true)  	{ -		LLError::Settings::reset(); +		LLError::Settings::getInstance()->reset();  		LLError::setDefaultLevel(LLError::LEVEL_INFO);  		LLError::setFatalFunction(LLError::crashAndLoop); @@ -613,11 +612,13 @@ namespace  		// log_to_stderr is only false in the unit and integration tests to keep builds quieter  		if (log_to_stderr && shouldLogToStderr())  		{ -			LLError::addRecorder(new RecordToStderr(stderrLogWantsTime())); +			LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime())); +			LLError::addRecorder(recordToStdErr);  		}  #if LL_WINDOWS -		LLError::addRecorder(new RecordToWinDebug); +		LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug()); +		LLError::addRecorder(recordToWinDebug);  #endif  		LogControlFile& e = LogControlFile::fromDirectory(dir); @@ -645,7 +646,8 @@ namespace LLError  		}  		commonInit(dir);  #if !LL_WINDOWS -		addRecorder(new RecordToSyslog(identity)); +		LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity)); +		addRecorder(recordToSyslog);  #endif  	} @@ -656,72 +658,67 @@ namespace LLError  	void setPrintLocation(bool print)  	{ -		Settings& s = Settings::get(); -		s.mPrintLocation = print; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mPrintLocation = print;  	}  	void setFatalFunction(const FatalFunction& f)  	{ -		Settings& s = Settings::get(); -		s.mCrashFunction = f; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mCrashFunction = f;  	}      FatalFunction getFatalFunction()      { -        Settings& s = Settings::get(); -        return s.mCrashFunction; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +        return s->mCrashFunction;      }  	void setTimeFunction(TimeFunction f)  	{ -		Settings& s = Settings::get(); -		s.mTimeFunction = f; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mTimeFunction = f;  	}  	void setDefaultLevel(ELevel level)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); -		g.invalidateCallSites(); -		s.mDefaultLevel = level; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mDefaultLevel = level;  	}  	ELevel getDefaultLevel()  	{ -		Settings& s = Settings::get(); -		return s.mDefaultLevel; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		return s->mDefaultLevel;  	}  	void setFunctionLevel(const std::string& function_name, ELevel level)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); -		g.invalidateCallSites(); -		s.mFunctionLevelMap[function_name] = level; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mFunctionLevelMap[function_name] = level;  	}  	void setClassLevel(const std::string& class_name, ELevel level)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); -		g.invalidateCallSites(); -		s.mClassLevelMap[class_name] = level; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mClassLevelMap[class_name] = level;  	}  	void setFileLevel(const std::string& file_name, ELevel level)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); -		g.invalidateCallSites(); -		s.mFileLevelMap[file_name] = level; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mFileLevelMap[file_name] = level;  	}  	void setTagLevel(const std::string& tag_name, ELevel level)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); -		g.invalidateCallSites(); -		s.mTagLevelMap[tag_name] = level; +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mTagLevelMap[tag_name] = level;  	}  	LLError::ELevel decodeLevel(std::string name) @@ -765,15 +762,14 @@ namespace LLError  {  	void configure(const LLSD& config)  	{ -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); +		Globals::getInstance()->invalidateCallSites(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); -		g.invalidateCallSites(); -		s.mFunctionLevelMap.clear(); -		s.mClassLevelMap.clear(); -		s.mFileLevelMap.clear(); -		s.mTagLevelMap.clear(); -		s.mUniqueLogMessages.clear(); +		s->mFunctionLevelMap.clear(); +		s->mClassLevelMap.clear(); +		s->mFileLevelMap.clear(); +		s->mTagLevelMap.clear(); +		s->mUniqueLogMessages.clear();  		setPrintLocation(config["print-location"]);  		setDefaultLevel(decodeLevel(config["default-level"])); @@ -786,10 +782,10 @@ namespace LLError  			ELevel level = decodeLevel(entry["level"]); -			setLevels(s.mFunctionLevelMap,	entry["functions"],	level); -			setLevels(s.mClassLevelMap,		entry["classes"],	level); -			setLevels(s.mFileLevelMap,		entry["files"],		level); -			setLevels(s.mTagLevelMap,		entry["tags"],		level); +			setLevels(s->mFunctionLevelMap,	entry["functions"],	level); +			setLevels(s->mClassLevelMap,	entry["classes"],	level); +			setLevels(s->mFileLevelMap,		entry["files"],		level); +			setLevels(s->mTagLevelMap,		entry["tags"],		level);  		}  	}  } @@ -803,10 +799,12 @@ namespace LLError  		mWantsLevel(true),  		mWantsLocation(false),  		mWantsFunctionName(true) -	{} +	{ +	}  	Recorder::~Recorder() -		{ } +	{ +	}  	bool Recorder::wantsTime()  	{  @@ -837,25 +835,25 @@ namespace LLError  		return mWantsFunctionName;  	} -	void addRecorder(Recorder* recorder) +	void addRecorder(RecorderPtr recorder)  	{ -		if (recorder == NULL) +		if (!recorder)  		{  			return;  		} -		Settings& s = Settings::get(); -		s.mRecorders.push_back(recorder); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mRecorders.push_back(recorder);  	} -	void removeRecorder(Recorder* recorder) +	void removeRecorder(RecorderPtr recorder)  	{ -		if (recorder == NULL) +		if (!recorder)  		{  			return;  		} -		Settings& s = Settings::get(); -		s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder), -							s.mRecorders.end()); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder), +							s->mRecorders.end());  	}  } @@ -863,51 +861,47 @@ namespace LLError  {  	void logToFile(const std::string& file_name)  	{ -		LLError::Settings& s = LLError::Settings::get(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); -		removeRecorder(s.mFileRecorder); -		delete s.mFileRecorder; -		s.mFileRecorder = NULL; -		s.mFileRecorderFileName.clear(); +		removeRecorder(s->mFileRecorder); +		s->mFileRecorder.reset(); +		s->mFileRecorderFileName.clear();  		if (file_name.empty())  		{  			return;  		} -		RecordToFile* f = new RecordToFile(file_name); -		if (!f->okay()) +		RecorderPtr recordToFile(new RecordToFile(file_name)); +		if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())  		{ -			delete f; -			return; +			s->mFileRecorderFileName = file_name; +			s->mFileRecorder = recordToFile; +			addRecorder(recordToFile);  		} - -		s.mFileRecorderFileName = file_name; -		s.mFileRecorder = f; -		addRecorder(f);  	}  	void logToFixedBuffer(LLLineBuffer* fixedBuffer)  	{ -		LLError::Settings& s = LLError::Settings::get(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); -		removeRecorder(s.mFixedBufferRecorder); -		delete s.mFixedBufferRecorder; -		s.mFixedBufferRecorder = NULL; +		removeRecorder(s->mFixedBufferRecorder); +		s->mFixedBufferRecorder.reset();  		if (!fixedBuffer)  		{  			return;  		} -		s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); -		addRecorder(s.mFixedBufferRecorder); +		RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer)); +		s->mFixedBufferRecorder = recordToFixedBuffer; +		addRecorder(recordToFixedBuffer);  	}  	std::string logFileName()  	{ -		LLError::Settings& s = LLError::Settings::get(); -		return s.mFileRecorderFileName; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		return s->mFileRecorderFileName;  	}  } @@ -916,24 +910,24 @@ namespace  	void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)  	{  		LLError::ELevel level = site.mLevel; -		LLError::Settings& s = LLError::Settings::get(); +		LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); -		for (Recorders::const_iterator i = s.mRecorders.begin(); -			i != s.mRecorders.end(); +		for (Recorders::const_iterator i = s->mRecorders.begin(); +			i != s->mRecorders.end();  			++i)  		{ -			LLError::Recorder* r = *i; +			LLError::RecorderPtr r = *i;  			std::ostringstream message_stream; -			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation)) +			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))  			{  				message_stream << site.mLocationString << " ";  			} -			if (show_time && r->wantsTime() && s.mTimeFunction != NULL) +			if (show_time && r->wantsTime() && s->mTimeFunction != NULL)  			{ -				message_stream << s.mTimeFunction() << " "; +				message_stream << s->mTimeFunction() << " ";  			}  			if (show_level && r->wantsLevel()) @@ -1060,10 +1054,9 @@ namespace LLError  			return false;  		} -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); -		s.mShouldLogCallCounter++; +		s->mShouldLogCallCounter++;  		const std::string& class_name = className(site.mClassInfo);  		std::string function_name = functionName(site.mFunction); @@ -1077,21 +1070,21 @@ namespace LLError  			function_name = class_name + "::" + function_name;  		} -		ELevel compareLevel = s.mDefaultLevel; +		ELevel compareLevel = s->mDefaultLevel;  		// The most specific match found will be used as the log level,  		// since the computation short circuits.  		// So, in increasing order of importance:  		// Default < Tags < File < Class < Function -		checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel) -		|| checkLevelMap(s.mClassLevelMap, class_name, compareLevel) -		|| checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel) +		checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel) +		|| checkLevelMap(s->mClassLevelMap, class_name, compareLevel) +		|| checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)  		|| (site.mTagCount > 0 -			? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel)  +			? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel)   			: false);  		site.mCached = true; -		g.addCallSite(site); +		Globals::getInstance()->addCallSite(site);  		return site.mShouldLog = site.mLevel >= compareLevel;  	} @@ -1101,12 +1094,12 @@ namespace LLError  		LogLock lock;  		if (lock.ok())  		{ -			Globals& g = Globals::get(); +			Globals* g = Globals::getInstance(); -			if (!g.messageStreamInUse) +			if (!g->messageStreamInUse)  			{ -				g.messageStreamInUse = true; -				return &g.messageStream; +				g->messageStreamInUse = true; +				return &g->messageStream;  			}  		} @@ -1131,13 +1124,12 @@ namespace LLError  		   message[127] = '\0' ;  	   } -	   Globals& g = Globals::get(); - -       if (out == &g.messageStream) +	   Globals* g = Globals::getInstance(); +       if (out == &g->messageStream)         { -           g.messageStream.clear(); -           g.messageStream.str(""); -           g.messageStreamInUse = false; +           g->messageStream.clear(); +           g->messageStream.str(""); +           g->messageStreamInUse = false;         }         else         { @@ -1154,15 +1146,15 @@ namespace LLError  			return;  		} -		Globals& g = Globals::get(); -		Settings& s = Settings::get(); +		Globals* g = Globals::getInstance(); +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();  		std::string message = out->str(); -		if (out == &g.messageStream) +		if (out == &g->messageStream)  		{ -			g.messageStream.clear(); -			g.messageStream.str(""); -			g.messageStreamInUse = false; +			g->messageStream.clear(); +			g->messageStream.str(""); +			g->messageStreamInUse = false;  		}  		else  		{ @@ -1178,8 +1170,8 @@ namespace LLError  		if (site.mPrintOnce)  		{ -			std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message); -			if (messageIter != s.mUniqueLogMessages.end()) +			std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message); +			if (messageIter != s->mUniqueLogMessages.end())  			{  				messageIter->second++;  				unsigned int num_messages = messageIter->second; @@ -1195,7 +1187,7 @@ namespace LLError  			else   			{  				message_stream << "ONCE: "; -				s.mUniqueLogMessages[message] = 1; +				s->mUniqueLogMessages[message] = 1;  			}  		} @@ -1203,23 +1195,23 @@ namespace LLError  		writeToRecorders(site, message_stream.str()); -		if (site.mLevel == LEVEL_ERROR  &&  s.mCrashFunction) +		if (site.mLevel == LEVEL_ERROR  &&  s->mCrashFunction)  		{ -			s.mCrashFunction(message_stream.str()); +			s->mCrashFunction(message_stream.str());  		}  	}  }  namespace LLError  { -	Settings* saveAndResetSettings() +	SettingsStoragePtr saveAndResetSettings()  	{ -		return Settings::saveAndReset(); +		return Settings::getInstance()->saveAndReset();  	} -	void restoreSettings(Settings* s) +	void restoreSettings(SettingsStoragePtr pSettingsStorage)  	{ -		return Settings::restore(s); +		return Settings::getInstance()->restore(pSettingsStorage);  	}  	std::string removePrefix(std::string& s, const std::string& p) @@ -1265,8 +1257,8 @@ namespace LLError  	int shouldLogCallCount()  	{ -		Settings& s = Settings::get(); -		return s.mShouldLogCallCounter; +		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); +		return s->mShouldLogCallCounter;  	}  #if LL_WINDOWS @@ -1375,15 +1367,9 @@ namespace LLError  #endif  	//static -   void LLCallStacks::push(const char* function, const int line) +   void LLCallStacks::allocateStackBuffer()     { -	   CallStacksLogLock lock; -       if (!lock.ok()) -       { -           return; -       } - -	   if(!sBuffer) +	   if(sBuffer == NULL)  	   {  		   sBuffer = new char*[512] ;  		   sBuffer[0] = new char[512 * 128] ; @@ -1393,6 +1379,31 @@ namespace LLError  		   }  		   sIndex = 0 ;  	   } +   } + +   void LLCallStacks::freeStackBuffer() +   { +	   if(sBuffer != NULL) +	   { +		   delete [] sBuffer[0] ; +		   delete [] sBuffer ; +		   sBuffer = NULL ; +	   } +   } + +   //static +   void LLCallStacks::push(const char* function, const int line) +   { +	   CallStacksLogLock lock; +       if (!lock.ok()) +       { +           return; +       } + +	   if(sBuffer == NULL) +	   { +		   allocateStackBuffer(); +	   }  	   if(sIndex > 511)  	   { @@ -1424,15 +1435,9 @@ namespace LLError             return;         } -	   if(!sBuffer) +	   if(sBuffer == NULL)  	   { -		   sBuffer = new char*[512] ; -		   sBuffer[0] = new char[512 * 128] ; -		   for(S32 i = 1 ; i < 512 ; i++) -		   { -			   sBuffer[i] = sBuffer[i-1] + 128 ; -		   } -		   sIndex = 0 ; +		   allocateStackBuffer();  	   }  	   if(sIndex > 511) @@ -1463,11 +1468,9 @@ namespace LLError             LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;         } -	   if(sBuffer) +	   if(sBuffer != NULL)  	   { -		   delete[] sBuffer[0] ; -		   delete[] sBuffer ; -		   sBuffer = NULL ; +		   freeStackBuffer();  	   }     } @@ -1477,5 +1480,10 @@ namespace LLError         sIndex = 0 ;     } +   //static +   void LLCallStacks::cleanup() +   { +	   freeStackBuffer(); +   }  } diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index bc80e64423..63040e1772 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -261,6 +261,9 @@ namespace LLError     private:         static char**  sBuffer ;  	   static S32     sIndex ; + +	   static void allocateStackBuffer(); +	   static void freeStackBuffer();     public:     	   static void push(const char* function, const int line) ; @@ -268,6 +271,7 @@ namespace LLError         static void print() ;         static void clear() ;  	   static void end(std::ostringstream* _out) ; +	   static void cleanup();     };   } diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index aab695094c..56ac52e5de 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -29,7 +29,10 @@  #define LL_LLERRORCONTROL_H  #include "llerror.h" +#include "llpointer.h" +#include "llrefcount.h"  #include "boost/function.hpp" +#include "boost/shared_ptr.hpp"  #include <string>  class LLSD; @@ -156,16 +159,14 @@ namespace LLError  				mWantsFunctionName;  	}; +	typedef boost::shared_ptr<Recorder> RecorderPtr; +  	/** -	 * @NOTE: addRecorder() conveys ownership to the underlying Settings -	 * object -- when destroyed, it will @em delete the passed Recorder*! -	 */ -	LL_COMMON_API void addRecorder(Recorder*); -	/** -	 * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its -	 * lifespan becomes the caller's problem. +	 * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership +	 * while still ensuring that the allocated memory is eventually freed  	 */ -	LL_COMMON_API void removeRecorder(Recorder*); +	LL_COMMON_API void addRecorder(RecorderPtr); +	LL_COMMON_API void removeRecorder(RecorderPtr);  		// each error message is passed to each recorder via recordMessage()  	LL_COMMON_API void logToFile(const std::string& filename); @@ -182,9 +183,9 @@ namespace LLError  		Utilities for use by the unit tests of LLError itself.  	*/ -	class Settings; -	LL_COMMON_API Settings* saveAndResetSettings(); -	LL_COMMON_API void restoreSettings(Settings *); +	typedef LLPointer<LLRefCount> SettingsStoragePtr; +	LL_COMMON_API SettingsStoragePtr saveAndResetSettings(); +	LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);  	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);  	LL_COMMON_API int shouldLogCallCount(); diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 2532566319..7aa87fcd0e 100755 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -31,6 +31,7 @@  #include <vector>  #include <list>  #include <boost/function.hpp> +#include <boost/shared_ptr.hpp>  #include <boost/type_traits/is_convertible.hpp>  #include <boost/type_traits/is_enum.hpp>  #include <boost/unordered_map.hpp> @@ -629,7 +630,7 @@ namespace LLInitParam  		UserData*			mUserData;  	}; -	typedef ParamDescriptor* ParamDescriptorPtr; +	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;  	// each derived Block class keeps a static data structure maintaining offsets to various params  	class LL_COMMON_API BlockDescriptor diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index b28c5ba4b3..a5aaff10c5 100755 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -56,9 +56,9 @@ namespace tut  	{  	public:  		TestRecorder() { mWantsTime = false; } -		~TestRecorder() { LLError::removeRecorder(this); } +		virtual ~TestRecorder() {  } -		void recordMessage(LLError::ELevel level, +		virtual void recordMessage(LLError::ELevel level,  						   const std::string& message)  		{  			mMessages.push_back(message); @@ -85,15 +85,11 @@ namespace tut  	struct ErrorTestData  	{ -		// addRecorder() expects to be able to later delete the passed -		// Recorder*. Even though removeRecorder() reclaims ownership, passing -		// a pointer to a data member rather than a heap Recorder subclass -		// instance would just be Wrong. -		TestRecorder* mRecorder; -		LLError::Settings* mPriorErrorSettings; +		LLError::RecorderPtr mRecorder; +		LLError::SettingsStoragePtr mPriorErrorSettings;  		ErrorTestData(): -			mRecorder(new TestRecorder) +			mRecorder(new TestRecorder())  		{  			fatalWasCalled = false; @@ -106,13 +102,32 @@ namespace tut  		~ErrorTestData()  		{  			LLError::removeRecorder(mRecorder); -			delete mRecorder;  			LLError::restoreSettings(mPriorErrorSettings);  		} +		int countMessages() +		{ +			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages(); +		} + +		void clearMessages() +		{ +			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages(); +		} + +		void setWantsTime(bool t) +		{ +			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->setWantsTime(t); +		} + +		std::string message(int n) +		{ +			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n); +		} +  		void ensure_message_count(int expectedCount)  		{ -			ensure_equals("message count", mRecorder->countMessages(), expectedCount); +			ensure_equals("message count", countMessages(), expectedCount);  		}  		void ensure_message_contains(int n, const std::string& expectedText) @@ -120,7 +135,7 @@ namespace tut  			std::ostringstream test_name;  			test_name << "testing message " << n; -			ensure_contains(test_name.str(), mRecorder->message(n), expectedText); +			ensure_contains(test_name.str(), message(n), expectedText);  		}  		void ensure_message_does_not_contain(int n, const std::string& expectedText) @@ -128,7 +143,7 @@ namespace tut  			std::ostringstream test_name;  			test_name << "testing message " << n; -			ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText); +			ensure_does_not_contain(test_name.str(), message(n), expectedText);  		}  	}; @@ -385,15 +400,15 @@ namespace  	}  	typedef std::string (*LogFromFunction)(bool); -	void testLogName(tut::TestRecorder* recorder, LogFromFunction f, +	void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,  		const std::string& class_name = "")  	{ -		recorder->clearMessages(); +		boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();  		std::string name = f(false);  		f(true); -		std::string messageWithoutName = recorder->message(0); -		std::string messageWithName = recorder->message(1); +		std::string messageWithoutName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0); +		std::string messageWithName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);  		ensure_has(name + " logged without name",  			messageWithoutName, name); @@ -528,12 +543,12 @@ namespace tut  	{  		LLError::setTimeFunction(roswell); -		mRecorder->setWantsTime(false); +		setWantsTime(false);  		ufoSighting();  		ensure_message_contains(0, "ufo");  		ensure_message_does_not_contain(0, roswell()); -		mRecorder->setWantsTime(true); +		setWantsTime(true);  		ufoSighting();  		ensure_message_contains(1, "ufo");  		ensure_message_contains(1, roswell()); @@ -545,13 +560,13 @@ namespace tut  	{  		LLError::setPrintLocation(true);  		LLError::setTimeFunction(roswell); -		mRecorder->setWantsTime(true); +		setWantsTime(true);  		std::string location,  					function;  		writeReturningLocationAndFunction(location, function);  		ensure_equals("order is location time type function message", -			mRecorder->message(0), +			message(0),  			location + roswell() + " INFO: " + function + ": apple");  	} @@ -559,19 +574,19 @@ namespace tut  		// multiple recorders  	void ErrorTestObject::test<11>()  	{ -		TestRecorder* altRecorder(new TestRecorder); +		LLError::RecorderPtr altRecorder(new TestRecorder());  		LLError::addRecorder(altRecorder);  		LL_INFOS() << "boo" << LL_ENDL;  		ensure_message_contains(0, "boo"); -		ensure_equals("alt recorder count", altRecorder->countMessages(), 1); -		ensure_contains("alt recorder message 0", altRecorder->message(0), "boo"); +		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1); +		ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");  		LLError::setTimeFunction(roswell); -		TestRecorder* anotherRecorder(new TestRecorder); -		anotherRecorder->setWantsTime(true); +		LLError::RecorderPtr anotherRecorder(new TestRecorder()); +		boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->setWantsTime(true);  		LLError::addRecorder(anotherRecorder);  		LL_INFOS() << "baz" << LL_ENDL; @@ -579,10 +594,13 @@ namespace tut  		std::string when = roswell();  		ensure_message_does_not_contain(1, when); -		ensure_equals("alt recorder count", altRecorder->countMessages(), 2); -		ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when); -		ensure_equals("another recorder count", anotherRecorder->countMessages(), 1); -		ensure_contains("another recorder message 0", anotherRecorder->message(0), when); +		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2); +		ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when); +		ensure_equals("another recorder count", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1); +		ensure_contains("another recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when); + +		LLError::removeRecorder(altRecorder); +		LLError::removeRecorder(anotherRecorder);  	}  } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 3137bd8fea..785197ba11 100755 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -38,6 +38,7 @@  #include "stringize.h"  #include <boost/bind.hpp>  #include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp>  #include <list>  #include <string>  #include <stdexcept> @@ -81,72 +82,29 @@ struct WrapLLErrs      }      std::string error; -    LLError::Settings* mPriorErrorSettings; +    LLError::SettingsStoragePtr mPriorErrorSettings;      LLError::FatalFunction mPriorFatal;  };  /** - * LLError::addRecorder() accepts ownership of the passed Recorder* -- it - * expects to be able to delete it later. CaptureLog isa Recorder whose - * pointer we want to be able to pass without any ownership implications. - * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass - * that. Your heap RecorderProxy might later be deleted, but not yourRecorder. - */ -class RecorderProxy: public LLError::Recorder -{ -public: -    RecorderProxy(LLError::Recorder* recorder): -        mRecorder(recorder) -    {} - -    virtual void recordMessage(LLError::ELevel level, const std::string& message) -    { -        mRecorder->recordMessage(level, message); -    } - -    virtual bool wantsTime() -    { -        return mRecorder->wantsTime(); -    } - -private: -    LLError::Recorder* mRecorder; -}; - -/**   * Capture log messages. This is adapted (simplified) from the one in   * llerror_test.cpp.   */ -class CaptureLog : public LLError::Recorder, public boost::noncopyable +class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable  {  public: -    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG): -        // Mostly what we're trying to accomplish by saving and resetting -        // LLError::Settings is to bypass the default RecordToStderr and -        // RecordToWinDebug Recorders. As these are visible only inside -        // llerror.cpp, we can't just call LLError::removeRecorder() with -        // each. For certain tests we need to produce, capture and examine -        // DEBUG log messages -- but we don't want to spam the user's console -        // with that output. If it turns out that saveAndResetSettings() has -        // some bad effect, give up and just let the DEBUG level log messages -        // display. -        mOldSettings(LLError::saveAndResetSettings()), -        mProxy(new RecorderProxy(this)) +    CaptureLogRecorder() +		: LLError::Recorder(), +		boost::noncopyable(), +		mMessages()      { -        LLError::setFatalFunction(wouldHaveCrashed); -        LLError::setDefaultLevel(level); -        LLError::addRecorder(mProxy);      } -    ~CaptureLog() +    virtual ~CaptureLogRecorder()      { -        LLError::removeRecorder(mProxy); -        delete mProxy; -        LLError::restoreSettings(mOldSettings);      } -    void recordMessage(LLError::ELevel level, -                       const std::string& message) +    virtual void recordMessage(LLError::ELevel level, const std::string& message)      {          mMessages.push_back(message);      } @@ -154,7 +112,7 @@ public:      /// Don't assume the message we want is necessarily the LAST log message      /// emitted by the underlying code; search backwards through all messages      /// for the sought string. -    std::string messageWith(const std::string& search, bool required=true) +    std::string messageWith(const std::string& search, bool required)      {          for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend());               rmi != rmend; ++rmi) @@ -187,14 +145,63 @@ public:          return out;      } +private:      typedef std::list<std::string> MessageList;      MessageList mMessages; -    LLError::Settings* mOldSettings; -    LLError::Recorder* mProxy; +}; + +/** + * Capture log messages. This is adapted (simplified) from the one in + * llerror_test.cpp. + */ +class CaptureLog : public boost::noncopyable +{ +public: +    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG) +        // Mostly what we're trying to accomplish by saving and resetting +        // LLError::Settings is to bypass the default RecordToStderr and +        // RecordToWinDebug Recorders. As these are visible only inside +        // llerror.cpp, we can't just call LLError::removeRecorder() with +        // each. For certain tests we need to produce, capture and examine +        // DEBUG log messages -- but we don't want to spam the user's console +        // with that output. If it turns out that saveAndResetSettings() has +        // some bad effect, give up and just let the DEBUG level log messages +        // display. +		: boost::noncopyable(), +        mOldSettings(LLError::saveAndResetSettings()), +		mRecorder(new CaptureLogRecorder()) +    { +        LLError::setFatalFunction(wouldHaveCrashed); +        LLError::setDefaultLevel(level); +        LLError::addRecorder(mRecorder); +    } + +    ~CaptureLog() +    { +        LLError::removeRecorder(mRecorder); +        LLError::restoreSettings(mOldSettings); +    } + +    /// Don't assume the message we want is necessarily the LAST log message +    /// emitted by the underlying code; search backwards through all messages +    /// for the sought string. +    std::string messageWith(const std::string& search, bool required=true) +    { +		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required); +    } + +    std::ostream& streamto(std::ostream& out) const +    { +		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out); +    } + +private: +    LLError::SettingsStoragePtr mOldSettings; +	LLError::RecorderPtr mRecorder;  };  inline -std::ostream& operator<<(std::ostream& out, const CaptureLog& log) +std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log)  {      return log.streamto(out);  } | 
