Start up crash of LLErrorThread due to corrupt map in CheckLevelMap
Wrapped gSettings and the global objects returned by Settings::get() and Globals::get() in AIThreadSafe, forcing thread-safe access. This solves the problem of possible corruption of the various LevelMap's in LLError::Settings due to thread unsafe accesses.
This commit is contained in:
@@ -112,6 +112,7 @@ Aleric Inglewood
|
|||||||
IMP-664
|
IMP-664
|
||||||
IMP-670
|
IMP-670
|
||||||
IMP-701
|
IMP-701
|
||||||
|
IMP-734
|
||||||
Alissa Sabre
|
Alissa Sabre
|
||||||
VWR-81
|
VWR-81
|
||||||
VWR-83
|
VWR-83
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
|
|||||||
LLApp::LLApp() : mThreadErrorp(NULL)
|
LLApp::LLApp() : mThreadErrorp(NULL)
|
||||||
{
|
{
|
||||||
commonCtor();
|
commonCtor();
|
||||||
startErrorThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLApp::commonCtor()
|
void LLApp::commonCtor()
|
||||||
|
|||||||
@@ -256,9 +256,12 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void stepFrame();
|
void stepFrame();
|
||||||
|
|
||||||
private:
|
/**
|
||||||
|
* @ brief This method is called once as soon as logging is initialized.
|
||||||
|
*/
|
||||||
void startErrorThread();
|
void startErrorThread();
|
||||||
|
|
||||||
|
private:
|
||||||
void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions)
|
void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions)
|
||||||
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
||||||
static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
|
static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#include "llsdserialize.h"
|
#include "llsdserialize.h"
|
||||||
#include "llstl.h"
|
#include "llstl.h"
|
||||||
#include "lltimer.h"
|
#include "lltimer.h"
|
||||||
|
#include "aithreadsafe.h"
|
||||||
|
|
||||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||||
|
|
||||||
@@ -357,12 +358,15 @@ namespace
|
|||||||
void addCallSite(LLError::CallSite&);
|
void addCallSite(LLError::CallSite&);
|
||||||
void invalidateCallSites();
|
void invalidateCallSites();
|
||||||
|
|
||||||
static Globals& get();
|
static AIThreadSafeSimple<Globals>& get();
|
||||||
// return the one instance of the globals
|
// return the one instance of the globals
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CallSiteVector callSites;
|
CallSiteVector callSites;
|
||||||
|
|
||||||
|
friend class AIThreadSafeSimpleDC<Globals>; // Calls constructor.
|
||||||
|
friend class AIThreadSafeSimple<Globals>; // Calls destructor.
|
||||||
|
|
||||||
Globals()
|
Globals()
|
||||||
: messageStreamInUse(false)
|
: messageStreamInUse(false)
|
||||||
{ }
|
{ }
|
||||||
@@ -386,7 +390,7 @@ namespace
|
|||||||
callSites.clear();
|
callSites.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Globals& Globals::get()
|
AIThreadSafeSimple<Globals>& Globals::get()
|
||||||
{
|
{
|
||||||
/* This pattern, of returning a reference to a static function
|
/* This pattern, of returning a reference to a static function
|
||||||
variable, is to ensure that this global is constructed before
|
variable, is to ensure that this global is constructed before
|
||||||
@@ -394,8 +398,8 @@ namespace
|
|||||||
is.
|
is.
|
||||||
See C++ FAQ Lite, sections 10.12 through 10.14
|
See C++ FAQ Lite, sections 10.12 through 10.14
|
||||||
*/
|
*/
|
||||||
static Globals* globals = new Globals;
|
static AIThreadSafeSimpleDCRootPool<Globals>* ts_globals_ptr = new AIThreadSafeSimpleDCRootPool<Globals>;
|
||||||
return *globals;
|
return *ts_globals_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,13 +428,16 @@ namespace LLError
|
|||||||
|
|
||||||
int shouldLogCallCounter;
|
int shouldLogCallCounter;
|
||||||
|
|
||||||
static Settings& get();
|
static AIThreadSafeSimple<Settings>& get();
|
||||||
|
|
||||||
static void reset();
|
static void reset();
|
||||||
static Settings* saveAndReset();
|
static AIThreadSafeSimple<Settings>* saveAndReset();
|
||||||
static void restore(Settings*);
|
static void restore(AIThreadSafeSimple<Settings>*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class AIThreadSafeBits<Settings>; // Calls destructor.
|
||||||
|
friend class AIThreadSafeSimpleDC<Settings>; // Calls constructor.
|
||||||
|
|
||||||
Settings()
|
Settings()
|
||||||
: printLocation(false),
|
: printLocation(false),
|
||||||
defaultLevel(LLError::LEVEL_DEBUG),
|
defaultLevel(LLError::LEVEL_DEBUG),
|
||||||
@@ -446,53 +453,42 @@ namespace LLError
|
|||||||
for_each(recorders.begin(), recorders.end(),
|
for_each(recorders.begin(), recorders.end(),
|
||||||
DeletePointer());
|
DeletePointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Settings*& getPtr();
|
static AIThreadSafeSimple<Settings>* sSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Pointer to current AIThreadSafeSimple<Settings> object if any (NULL otherwise).
|
||||||
|
AIThreadSafeSimple<Settings>* Settings::sSettings;
|
||||||
|
|
||||||
Settings& Settings::get()
|
AIThreadSafeSimple<Settings>& Settings::get()
|
||||||
{
|
{
|
||||||
Settings* p = getPtr();
|
if (!sSettings)
|
||||||
if (!p)
|
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
p = getPtr();
|
|
||||||
}
|
}
|
||||||
return *p;
|
return *sSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::reset()
|
void Settings::reset()
|
||||||
{
|
{
|
||||||
Globals::get().invalidateCallSites();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
|
delete sSettings;
|
||||||
Settings*& p = getPtr();
|
sSettings = new AIThreadSafeSimpleDC<Settings>;
|
||||||
delete p;
|
|
||||||
p = new Settings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings* Settings::saveAndReset()
|
AIThreadSafeSimple<Settings>* Settings::saveAndReset()
|
||||||
{
|
{
|
||||||
Globals::get().invalidateCallSites();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
|
AIThreadSafeSimple<Settings>* originalSettings = sSettings;
|
||||||
Settings*& p = getPtr();
|
sSettings = new AIThreadSafeSimpleDC<Settings>;
|
||||||
Settings* originalSettings = p;
|
|
||||||
p = new Settings();
|
|
||||||
return originalSettings;
|
return originalSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::restore(Settings* originalSettings)
|
void Settings::restore(AIThreadSafeSimple<Settings>* originalSettings)
|
||||||
{
|
{
|
||||||
Globals::get().invalidateCallSites();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
|
delete sSettings;
|
||||||
Settings*& p = getPtr();
|
sSettings = originalSettings;
|
||||||
delete p;
|
|
||||||
p = originalSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings*& Settings::getPtr()
|
|
||||||
{
|
|
||||||
static Settings* currentSettings = NULL;
|
|
||||||
return currentSettings;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,68 +592,64 @@ namespace LLError
|
|||||||
commonInit(dir);
|
commonInit(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPrintLocation(AIAccess<Settings> const& settings_w, bool print)
|
||||||
|
{
|
||||||
|
settings_w->printLocation = print;
|
||||||
|
}
|
||||||
|
|
||||||
void setPrintLocation(bool print)
|
void setPrintLocation(bool print)
|
||||||
{
|
{
|
||||||
Settings& s = Settings::get();
|
setPrintLocation(AIAccess<Settings>(Settings::get()), print);
|
||||||
s.printLocation = print;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFatalFunction(const FatalFunction& f)
|
void setFatalFunction(const FatalFunction& f)
|
||||||
{
|
{
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->crashFunction = f;
|
||||||
s.crashFunction = f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FatalFunction getFatalFunction()
|
FatalFunction getFatalFunction()
|
||||||
{
|
{
|
||||||
Settings& s = Settings::get();
|
return AIAccess<Settings>(Settings::get())->crashFunction;
|
||||||
return s.crashFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTimeFunction(TimeFunction f)
|
void setTimeFunction(TimeFunction f)
|
||||||
{
|
{
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->timeFunction = f;
|
||||||
s.timeFunction = f;
|
}
|
||||||
|
|
||||||
|
void setDefaultLevel(AIAccess<Settings> const& settings_w, ELevel level)
|
||||||
|
{
|
||||||
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
|
settings_w->defaultLevel = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDefaultLevel(ELevel level)
|
void setDefaultLevel(ELevel level)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
setDefaultLevel(AIAccess<Settings>(Settings::get()), level);
|
||||||
Settings& s = Settings::get();
|
|
||||||
g.invalidateCallSites();
|
|
||||||
s.defaultLevel = level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFunctionLevel(const std::string& function_name, ELevel level)
|
void setFunctionLevel(const std::string& function_name, ELevel level)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->functionLevelMap[function_name] = level;
|
||||||
g.invalidateCallSites();
|
|
||||||
s.functionLevelMap[function_name] = level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setClassLevel(const std::string& class_name, ELevel level)
|
void setClassLevel(const std::string& class_name, ELevel level)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->classLevelMap[class_name] = level;
|
||||||
g.invalidateCallSites();
|
|
||||||
s.classLevelMap[class_name] = level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFileLevel(const std::string& file_name, ELevel level)
|
void setFileLevel(const std::string& file_name, ELevel level)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->fileLevelMap[file_name] = level;
|
||||||
g.invalidateCallSites();
|
|
||||||
s.fileLevelMap[file_name] = level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTagLevel(const std::string& tag_name, ELevel level)
|
void setTagLevel(const std::string& tag_name, ELevel level)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
Settings& s = Settings::get();
|
AIAccess<Settings>(Settings::get())->tagLevelMap[tag_name] = level;
|
||||||
g.invalidateCallSites();
|
|
||||||
s.tagLevelMap[tag_name] = level;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,18 +693,16 @@ namespace LLError
|
|||||||
{
|
{
|
||||||
void configure(const LLSD& config)
|
void configure(const LLSD& config)
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Settings> settings_w(Settings::get());
|
||||||
Settings& s = Settings::get();
|
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||||
|
settings_w->functionLevelMap.clear();
|
||||||
|
settings_w->classLevelMap.clear();
|
||||||
|
settings_w->fileLevelMap.clear();
|
||||||
|
settings_w->tagLevelMap.clear();
|
||||||
|
settings_w->uniqueLogMessages.clear();
|
||||||
|
|
||||||
g.invalidateCallSites();
|
setPrintLocation(settings_w, config["print-location"]);
|
||||||
s.functionLevelMap.clear();
|
setDefaultLevel(settings_w, decodeLevel(config["default-level"]));
|
||||||
s.classLevelMap.clear();
|
|
||||||
s.fileLevelMap.clear();
|
|
||||||
s.tagLevelMap.clear();
|
|
||||||
s.uniqueLogMessages.clear();
|
|
||||||
|
|
||||||
setPrintLocation(config["print-location"]);
|
|
||||||
setDefaultLevel(decodeLevel(config["default-level"]));
|
|
||||||
|
|
||||||
LLSD sets = config["settings"];
|
LLSD sets = config["settings"];
|
||||||
LLSD::array_const_iterator a, end;
|
LLSD::array_const_iterator a, end;
|
||||||
@@ -722,10 +712,10 @@ namespace LLError
|
|||||||
|
|
||||||
ELevel level = decodeLevel(entry["level"]);
|
ELevel level = decodeLevel(entry["level"]);
|
||||||
|
|
||||||
setLevels(s.functionLevelMap, entry["functions"], level);
|
setLevels(settings_w->functionLevelMap, entry["functions"], level);
|
||||||
setLevels(s.classLevelMap, entry["classes"], level);
|
setLevels(settings_w->classLevelMap, entry["classes"], level);
|
||||||
setLevels(s.fileLevelMap, entry["files"], level);
|
setLevels(settings_w->fileLevelMap, entry["files"], level);
|
||||||
setLevels(s.tagLevelMap, entry["tags"], level);
|
setLevels(settings_w->tagLevelMap, entry["tags"], level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -742,26 +732,34 @@ namespace LLError
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void addRecorder(Recorder* recorder)
|
void addRecorder(AIAccess<Settings> const& settings_w, Recorder* recorder)
|
||||||
{
|
{
|
||||||
if (recorder == NULL)
|
if (recorder == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Settings& s = Settings::get();
|
settings_w->recorders.push_back(recorder);
|
||||||
s.recorders.push_back(recorder);
|
}
|
||||||
|
|
||||||
|
void addRecorder(Recorder* recorder)
|
||||||
|
{
|
||||||
|
addRecorder(AIAccess<Settings>(Settings::get()), recorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeRecorder(AIAccess<Settings> const& settings_w, Recorder* recorder)
|
||||||
|
{
|
||||||
|
if (recorder == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settings_w->recorders.erase(
|
||||||
|
std::remove(settings_w->recorders.begin(), settings_w->recorders.end(), recorder),
|
||||||
|
settings_w->recorders.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeRecorder(Recorder* recorder)
|
void removeRecorder(Recorder* recorder)
|
||||||
{
|
{
|
||||||
if (recorder == NULL)
|
removeRecorder(AIAccess<Settings>(Settings::get()), recorder);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Settings& s = Settings::get();
|
|
||||||
s.recorders.erase(
|
|
||||||
std::remove(s.recorders.begin(), s.recorders.end(), recorder),
|
|
||||||
s.recorders.end());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,12 +767,12 @@ namespace LLError
|
|||||||
{
|
{
|
||||||
void logToFile(const std::string& file_name)
|
void logToFile(const std::string& file_name)
|
||||||
{
|
{
|
||||||
LLError::Settings& s = LLError::Settings::get();
|
AIAccess<Settings> settings_w(Settings::get());
|
||||||
|
|
||||||
removeRecorder(s.fileRecorder);
|
removeRecorder(settings_w, settings_w->fileRecorder);
|
||||||
delete s.fileRecorder;
|
delete settings_w->fileRecorder;
|
||||||
s.fileRecorder = NULL;
|
settings_w->fileRecorder = NULL;
|
||||||
s.fileRecorderFileName.clear();
|
settings_w->fileRecorderFileName.clear();
|
||||||
|
|
||||||
if (file_name.empty())
|
if (file_name.empty())
|
||||||
{
|
{
|
||||||
@@ -788,54 +786,51 @@ namespace LLError
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fileRecorderFileName = file_name;
|
settings_w->fileRecorderFileName = file_name;
|
||||||
s.fileRecorder = f;
|
settings_w->fileRecorder = f;
|
||||||
addRecorder(f);
|
addRecorder(settings_w, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
|
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
|
||||||
{
|
{
|
||||||
LLError::Settings& s = LLError::Settings::get();
|
AIAccess<Settings> settings_w(Settings::get());
|
||||||
|
|
||||||
removeRecorder(s.fixedBufferRecorder);
|
removeRecorder(settings_w, settings_w->fixedBufferRecorder);
|
||||||
delete s.fixedBufferRecorder;
|
delete settings_w->fixedBufferRecorder;
|
||||||
s.fixedBufferRecorder = NULL;
|
settings_w->fixedBufferRecorder = NULL;
|
||||||
|
|
||||||
if (!fixedBuffer)
|
if (!fixedBuffer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
|
settings_w->fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
|
||||||
addRecorder(s.fixedBufferRecorder);
|
addRecorder(settings_w, settings_w->fixedBufferRecorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string logFileName()
|
std::string logFileName()
|
||||||
{
|
{
|
||||||
LLError::Settings& s = LLError::Settings::get();
|
return AIAccess<Settings>(Settings::get())->fileRecorderFileName;
|
||||||
return s.fileRecorderFileName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void writeToRecorders(LLError::ELevel level, const std::string& message)
|
void writeToRecorders(AIAccess<LLError::Settings> const& settings_w, LLError::ELevel level, const std::string& message)
|
||||||
{
|
{
|
||||||
LLError::Settings& s = LLError::Settings::get();
|
|
||||||
|
|
||||||
std::string messageWithTime;
|
std::string messageWithTime;
|
||||||
|
|
||||||
for (Recorders::const_iterator i = s.recorders.begin();
|
for (Recorders::const_iterator i = settings_w->recorders.begin();
|
||||||
i != s.recorders.end();
|
i != settings_w->recorders.end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
LLError::Recorder* r = *i;
|
LLError::Recorder* r = *i;
|
||||||
|
|
||||||
if (r->wantsTime() && s.timeFunction != NULL)
|
if (r->wantsTime() && settings_w->timeFunction != NULL)
|
||||||
{
|
{
|
||||||
if (messageWithTime.empty())
|
if (messageWithTime.empty())
|
||||||
{
|
{
|
||||||
messageWithTime = s.timeFunction() + " " + message;
|
messageWithTime = settings_w->timeFunction() + " " + message;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->recordMessage(level, messageWithTime);
|
r->recordMessage(level, messageWithTime);
|
||||||
@@ -955,10 +950,9 @@ namespace LLError
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Globals& g = Globals::get();
|
AIAccess<Settings> settings_w(Settings::get());
|
||||||
Settings& s = Settings::get();
|
|
||||||
|
|
||||||
s.shouldLogCallCounter += 1;
|
settings_w->shouldLogCallCounter += 1;
|
||||||
|
|
||||||
std::string class_name = className(site.mClassInfo);
|
std::string class_name = className(site.mClassInfo);
|
||||||
std::string function_name = functionName(site.mFunction);
|
std::string function_name = functionName(site.mFunction);
|
||||||
@@ -967,20 +961,20 @@ namespace LLError
|
|||||||
function_name = class_name + "::" + function_name;
|
function_name = class_name + "::" + function_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ELevel compareLevel = s.defaultLevel;
|
ELevel compareLevel = settings_w->defaultLevel;
|
||||||
|
|
||||||
// The most specific match found will be used as the log level,
|
// The most specific match found will be used as the log level,
|
||||||
// since the computation short circuits.
|
// since the computation short circuits.
|
||||||
// So, in increasing order of importance:
|
// So, in increasing order of importance:
|
||||||
// Default < Broad Tag < File < Class < Function < Narrow Tag
|
// Default < Broad Tag < File < Class < Function < Narrow Tag
|
||||||
((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false)
|
((site.mNarrowTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mNarrowTag, compareLevel) : false)
|
||||||
|| checkLevelMap(s.functionLevelMap, function_name, compareLevel)
|
|| checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel)
|
||||||
|| checkLevelMap(s.classLevelMap, class_name, compareLevel)
|
|| checkLevelMap(settings_w->classLevelMap, class_name, compareLevel)
|
||||||
|| checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel)
|
|| checkLevelMap(settings_w->fileLevelMap, abbreviateFile(site.mFile), compareLevel)
|
||||||
|| ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false);
|
|| ((site.mBroadTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mBroadTag, compareLevel) : false);
|
||||||
|
|
||||||
site.mCached = true;
|
site.mCached = true;
|
||||||
g.addCallSite(site);
|
AIAccess<Globals>(Globals::get())->addCallSite(site);
|
||||||
return site.mShouldLog = site.mLevel >= compareLevel;
|
return site.mShouldLog = site.mLevel >= compareLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -990,16 +984,16 @@ namespace LLError
|
|||||||
LogLock lock;
|
LogLock lock;
|
||||||
if (lock.ok())
|
if (lock.ok())
|
||||||
{
|
{
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals> globals(Globals::get());
|
||||||
|
|
||||||
if (!g.messageStreamInUse)
|
if (!globals->messageStreamInUse)
|
||||||
{
|
{
|
||||||
g.messageStreamInUse = true;
|
globals->messageStreamInUse = true;
|
||||||
return &g.messageStream;
|
return &globals->messageStream; // Returns pointer to member of unlocked object, apparently "protected" by having set globals->messageStreamInUse.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new std::ostringstream;
|
return new std::ostringstream; // Holy memory leak.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::flush(std::ostringstream* out, char* message)
|
void Log::flush(std::ostringstream* out, char* message)
|
||||||
@@ -1020,12 +1014,12 @@ namespace LLError
|
|||||||
message[127] = '\0' ;
|
message[127] = '\0' ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Globals& g = Globals::get();
|
AIAccess<Globals> globals(Globals::get());
|
||||||
if (out == &g.messageStream)
|
if (out == &globals->messageStream)
|
||||||
{
|
{
|
||||||
g.messageStream.clear();
|
globals->messageStream.clear();
|
||||||
g.messageStream.str("");
|
globals->messageStream.str("");
|
||||||
g.messageStreamInUse = false;
|
globals->messageStreamInUse = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1042,28 +1036,31 @@ namespace LLError
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Globals& g = Globals::get();
|
|
||||||
Settings& s = Settings::get();
|
|
||||||
|
|
||||||
std::string message = out->str();
|
std::string message = out->str();
|
||||||
if (out == &g.messageStream)
|
|
||||||
{
|
{
|
||||||
g.messageStream.clear();
|
AIAccess<Globals> globals(Globals::get());
|
||||||
g.messageStream.str("");
|
if (out == &globals->messageStream)
|
||||||
g.messageStreamInUse = false;
|
{
|
||||||
}
|
globals->messageStream.clear();
|
||||||
else
|
globals->messageStream.str("");
|
||||||
{
|
globals->messageStreamInUse = false;
|
||||||
delete out;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AIAccess<Settings> settings_w(Settings::get());
|
||||||
|
|
||||||
if (site.mLevel == LEVEL_ERROR)
|
if (site.mLevel == LEVEL_ERROR)
|
||||||
{
|
{
|
||||||
std::ostringstream fatalMessage;
|
std::ostringstream fatalMessage;
|
||||||
fatalMessage << abbreviateFile(site.mFile)
|
fatalMessage << abbreviateFile(site.mFile)
|
||||||
<< "(" << site.mLine << ") : error";
|
<< "(" << site.mLine << ") : error";
|
||||||
|
|
||||||
writeToRecorders(site.mLevel, fatalMessage.str());
|
writeToRecorders(settings_w, site.mLevel, fatalMessage.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1078,7 +1075,7 @@ namespace LLError
|
|||||||
default: prefix << "XXX: "; break;
|
default: prefix << "XXX: "; break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (s.printLocation)
|
if (settings_w->printLocation)
|
||||||
{
|
{
|
||||||
prefix << abbreviateFile(site.mFile)
|
prefix << abbreviateFile(site.mFile)
|
||||||
<< "(" << site.mLine << ") : ";
|
<< "(" << site.mLine << ") : ";
|
||||||
@@ -1096,8 +1093,8 @@ namespace LLError
|
|||||||
|
|
||||||
if (site.mPrintOnce)
|
if (site.mPrintOnce)
|
||||||
{
|
{
|
||||||
std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
|
std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message);
|
||||||
if (messageIter != s.uniqueLogMessages.end())
|
if (messageIter != settings_w->uniqueLogMessages.end())
|
||||||
{
|
{
|
||||||
messageIter->second++;
|
messageIter->second++;
|
||||||
unsigned int num_messages = messageIter->second;
|
unsigned int num_messages = messageIter->second;
|
||||||
@@ -1113,14 +1110,14 @@ namespace LLError
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix << "ONCE: ";
|
prefix << "ONCE: ";
|
||||||
s.uniqueLogMessages[message] = 1;
|
settings_w->uniqueLogMessages[message] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (site.mPrintOnce)
|
if (site.mPrintOnce)
|
||||||
{
|
{
|
||||||
std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
|
std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message);
|
||||||
if (messageIter != s.uniqueLogMessages.end())
|
if (messageIter != settings_w->uniqueLogMessages.end())
|
||||||
{
|
{
|
||||||
messageIter->second++;
|
messageIter->second++;
|
||||||
unsigned int num_messages = messageIter->second;
|
unsigned int num_messages = messageIter->second;
|
||||||
@@ -1136,18 +1133,18 @@ namespace LLError
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix << "ONCE: ";
|
prefix << "ONCE: ";
|
||||||
s.uniqueLogMessages[message] = 1;
|
settings_w->uniqueLogMessages[message] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix << message;
|
prefix << message;
|
||||||
message = prefix.str();
|
message = prefix.str();
|
||||||
|
|
||||||
writeToRecorders(site.mLevel, message);
|
writeToRecorders(settings_w, site.mLevel, message);
|
||||||
|
|
||||||
if (site.mLevel == LEVEL_ERROR && s.crashFunction)
|
if (site.mLevel == LEVEL_ERROR && settings_w->crashFunction)
|
||||||
{
|
{
|
||||||
s.crashFunction(message);
|
settings_w->crashFunction(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1157,14 +1154,16 @@ namespace LLError
|
|||||||
|
|
||||||
namespace LLError
|
namespace LLError
|
||||||
{
|
{
|
||||||
Settings* saveAndResetSettings()
|
class ThreadSafeSettings { };
|
||||||
|
|
||||||
|
ThreadSafeSettings* saveAndResetSettings()
|
||||||
{
|
{
|
||||||
return Settings::saveAndReset();
|
return reinterpret_cast<ThreadSafeSettings*>(Settings::saveAndReset());
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreSettings(Settings* s)
|
void restoreSettings(ThreadSafeSettings* s)
|
||||||
{
|
{
|
||||||
return Settings::restore(s);
|
Settings::restore(reinterpret_cast<AIThreadSafeSimple<Settings>*>(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string removePrefix(std::string& s, const std::string& p)
|
std::string removePrefix(std::string& s, const std::string& p)
|
||||||
@@ -1210,8 +1209,7 @@ namespace LLError
|
|||||||
|
|
||||||
int shouldLogCallCount()
|
int shouldLogCallCount()
|
||||||
{
|
{
|
||||||
Settings& s = Settings::get();
|
return AIAccess<Settings>(Settings::get())->shouldLogCallCounter;
|
||||||
return s.shouldLogCallCounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
|
|||||||
@@ -167,9 +167,9 @@ namespace LLError
|
|||||||
Utilities for use by the unit tests of LLError itself.
|
Utilities for use by the unit tests of LLError itself.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Settings;
|
class ThreadSafeSettings;
|
||||||
LL_COMMON_API Settings* saveAndResetSettings();
|
LL_COMMON_API ThreadSafeSettings* saveAndResetSettings();
|
||||||
LL_COMMON_API void restoreSettings(Settings *);
|
LL_COMMON_API void restoreSettings(ThreadSafeSettings *);
|
||||||
|
|
||||||
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
|
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
|
||||||
LL_COMMON_API int shouldLogCallCount();
|
LL_COMMON_API int shouldLogCallCount();
|
||||||
|
|||||||
@@ -66,7 +66,20 @@ const S32 CURRENT_VERSION = 101;
|
|||||||
//So, a global it is!
|
//So, a global it is!
|
||||||
bool gCOAEnabled = false;
|
bool gCOAEnabled = false;
|
||||||
|
|
||||||
LLControlVariable *LLControlVariable::getCOAActive()
|
LLControlVariable* LLControlVariable::getCOAActive()
|
||||||
|
{
|
||||||
|
//if no coa connection, return 'this'
|
||||||
|
//if per account is ON and this IS a parent, return child var
|
||||||
|
//if per account is ON and this IS NOT a parent, return 'this'
|
||||||
|
//if per account is OFF and this IS NOT a parent, return parent var
|
||||||
|
//if per account is OFF and this IS a parent, return 'this'
|
||||||
|
if(getCOAConnection() && gCOAEnabled == isCOAParent())
|
||||||
|
return getCOAConnection();
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLControlVariable const* LLControlVariable::getCOAActive() const
|
||||||
{
|
{
|
||||||
//if no coa connection, return 'this'
|
//if no coa connection, return 'this'
|
||||||
//if per account is ON and this IS a parent, return child var
|
//if per account is ON and this IS a parent, return child var
|
||||||
@@ -282,11 +295,9 @@ LLSD LLControlVariable::getSaveValue() const
|
|||||||
|
|
||||||
#if PROF_CTRL_CALLS
|
#if PROF_CTRL_CALLS
|
||||||
std::vector<std::pair<std::string, U32>> gSettingsCallMap;
|
std::vector<std::pair<std::string, U32>> gSettingsCallMap;
|
||||||
#endif //PROF_CTRL_CALLS
|
|
||||||
LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
|
static update_gSettingsCallMap(ctrl_name_table_t::const_iterator const& iter)
|
||||||
{
|
{
|
||||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
|
||||||
#if PROF_CTRL_CALLS
|
|
||||||
if(iter != mNameTable.end())
|
if(iter != mNameTable.end())
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, U32>>::iterator iter2 = gSettingsCallMap.begin();
|
std::vector<std::pair<std::string, U32>>::iterator iter2 = gSettingsCallMap.begin();
|
||||||
@@ -302,13 +313,32 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
|
|||||||
if(iter2 == gSettingsCallMap.end())
|
if(iter2 == gSettingsCallMap.end())
|
||||||
gSettingsCallMap.push_back(std::pair<std::string, U32>(name.c_str(),1));
|
gSettingsCallMap.push_back(std::pair<std::string, U32>(name.c_str(),1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif //PROF_CTRL_CALLS
|
||||||
|
|
||||||
|
LLControlVariable* LLControlGroup::getControl(std::string const& name)
|
||||||
|
{
|
||||||
|
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
||||||
|
#if PROF_CTRL_CALLS
|
||||||
|
update_gSettingsCallMap(iter);
|
||||||
#endif //PROF_CTRL_CALLS
|
#endif //PROF_CTRL_CALLS
|
||||||
if(iter != mNameTable.end())
|
if(iter != mNameTable.end())
|
||||||
return iter->second->getCOAActive();
|
return iter->second->getCOAActive();
|
||||||
else
|
else
|
||||||
return LLPointer<LLControlVariable>();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLControlVariable const* LLControlGroup::getControl(std::string const& name) const
|
||||||
|
{
|
||||||
|
ctrl_name_table_t::const_iterator iter = mNameTable.find(name);
|
||||||
|
#if PROF_CTRL_CALLS
|
||||||
|
update_gSettingsCallMap(iter);
|
||||||
|
#endif //PROF_CTRL_CALLS
|
||||||
|
if(iter != mNameTable.end())
|
||||||
|
return iter->second->getCOAActive();
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -502,9 +532,9 @@ std::string LLControlGroup::findString(const std::string& name)
|
|||||||
return LLStringUtil::null;
|
return LLStringUtil::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LLControlGroup::getString(const std::string& name)
|
std::string LLControlGroup::getString(const std::string& name) const
|
||||||
{
|
{
|
||||||
LLControlVariable* control = getControl(name);
|
LLControlVariable const* control = getControl(name);
|
||||||
|
|
||||||
if (control && control->isType(TYPE_STRING))
|
if (control && control->isType(TYPE_STRING))
|
||||||
return control->get().asString();
|
return control->get().asString();
|
||||||
@@ -649,9 +679,9 @@ LLSD LLControlGroup::getLLSD(const std::string& name)
|
|||||||
return LLSD();
|
return LLSD();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLControlGroup::controlExists(const std::string& name)
|
BOOL LLControlGroup::controlExists(const std::string& name) const
|
||||||
{
|
{
|
||||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
ctrl_name_table_t::const_iterator iter = mNameTable.find(name);
|
||||||
return iter != mNameTable.end();
|
return iter != mNameTable.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public:
|
|||||||
const std::string& getComment() const { return mComment; }
|
const std::string& getComment() const { return mComment; }
|
||||||
|
|
||||||
eControlType type() { return mType; }
|
eControlType type() { return mType; }
|
||||||
bool isType(eControlType tp) { return tp == mType; }
|
bool isType(eControlType tp) const { return tp == mType; }
|
||||||
|
|
||||||
void resetToDefault(bool fire_signal = false);
|
void resetToDefault(bool fire_signal = false);
|
||||||
|
|
||||||
@@ -153,7 +153,8 @@ public:
|
|||||||
bool isCOA() const { return mIsCOA; }
|
bool isCOA() const { return mIsCOA; }
|
||||||
bool isCOAParent() const { return mIsCOAParent; }
|
bool isCOAParent() const { return mIsCOAParent; }
|
||||||
LLControlVariable *getCOAConnection() const { return mCOAConnectedVar; }
|
LLControlVariable *getCOAConnection() const { return mCOAConnectedVar; }
|
||||||
LLControlVariable *getCOAActive();
|
LLControlVariable* getCOAActive();
|
||||||
|
LLControlVariable const* getCOAActive() const;
|
||||||
void setIsCOA(bool IsCOA) { mIsCOA=IsCOA; }
|
void setIsCOA(bool IsCOA) { mIsCOA=IsCOA; }
|
||||||
void setCOAConnect(LLControlVariable *pConnect, bool IsParent)
|
void setCOAConnect(LLControlVariable *pConnect, bool IsParent)
|
||||||
{
|
{
|
||||||
@@ -185,7 +186,8 @@ public:
|
|||||||
~LLControlGroup();
|
~LLControlGroup();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
LLPointer<LLControlVariable> getControl(const std::string& name);
|
LLControlVariable* getControl(std::string const& name);
|
||||||
|
LLControlVariable const* getControl(std::string const& name) const;
|
||||||
|
|
||||||
struct ApplyFunctor
|
struct ApplyFunctor
|
||||||
{
|
{
|
||||||
@@ -210,7 +212,7 @@ public:
|
|||||||
|
|
||||||
std::string findString(const std::string& name);
|
std::string findString(const std::string& name);
|
||||||
|
|
||||||
std::string getString(const std::string& name);
|
std::string getString(const std::string& name) const;
|
||||||
LLWString getWString(const std::string& name);
|
LLWString getWString(const std::string& name);
|
||||||
std::string getText(const std::string& name);
|
std::string getText(const std::string& name);
|
||||||
LLVector3 getVector3(const std::string& name);
|
LLVector3 getVector3(const std::string& name);
|
||||||
@@ -245,7 +247,7 @@ public:
|
|||||||
void setValue(const std::string& name, const LLSD& val);
|
void setValue(const std::string& name, const LLSD& val);
|
||||||
|
|
||||||
|
|
||||||
BOOL controlExists(const std::string& name);
|
BOOL controlExists(const std::string& name) const;
|
||||||
|
|
||||||
// Returns number of controls loaded, 0 if failed
|
// Returns number of controls loaded, 0 if failed
|
||||||
// If require_declaration is false, will auto-declare controls it finds
|
// If require_declaration is false, will auto-declare controls it finds
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
LLControlGroupReader() {}
|
LLControlGroupReader() {}
|
||||||
virtual ~LLControlGroupReader() {}
|
virtual ~LLControlGroupReader() {}
|
||||||
|
|
||||||
virtual std::string getString(const std::string& name) = 0;
|
virtual std::string getString(const std::string& name) const = 0;
|
||||||
//virtual LLWString getWString(const std::string& name) = 0;
|
//virtual LLWString getWString(const std::string& name) = 0;
|
||||||
virtual std::string getText(const std::string& name) = 0;
|
virtual std::string getText(const std::string& name) = 0;
|
||||||
//virtual LLVector3 getVector3(const std::string& name) = 0;
|
//virtual LLVector3 getVector3(const std::string& name) = 0;
|
||||||
|
|||||||
@@ -568,7 +568,10 @@ bool LLAppViewer::init()
|
|||||||
gDirUtilp->setSkinFolder("default");
|
gDirUtilp->setSkinFolder("default");
|
||||||
|
|
||||||
initLogging();
|
initLogging();
|
||||||
|
|
||||||
|
// Logging is initialized. Now it's safe to start the error thread.
|
||||||
|
startErrorThread();
|
||||||
|
|
||||||
// <edit>
|
// <edit>
|
||||||
gDeleteScheduler = new LLDeleteScheduler();
|
gDeleteScheduler = new LLDeleteScheduler();
|
||||||
gBuildNewViewsScheduler = new LLBuildNewViewsScheduler();
|
gBuildNewViewsScheduler = new LLBuildNewViewsScheduler();
|
||||||
@@ -1578,8 +1581,9 @@ bool LLAppViewer::initLogging()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
|
bool LLAppViewer::loadSettingsFromDirectory(AIReadAccess<settings_map_type> const& settings_r,
|
||||||
bool set_defaults)
|
std::string const& location_key,
|
||||||
|
bool set_defaults)
|
||||||
{
|
{
|
||||||
// Find and vet the location key.
|
// Find and vet the location key.
|
||||||
if(!mSettingsLocationList.has(location_key))
|
if(!mSettingsLocationList.has(location_key))
|
||||||
@@ -1606,11 +1610,13 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
|
|||||||
LLSD files = location.get("Files");
|
LLSD files = location.get("Files");
|
||||||
for(LLSD::map_iterator itr = files.beginMap(); itr != files.endMap(); ++itr)
|
for(LLSD::map_iterator itr = files.beginMap(); itr != files.endMap(); ++itr)
|
||||||
{
|
{
|
||||||
std::string settings_group = (*itr).first;
|
std::string const settings_group = (*itr).first;
|
||||||
|
settings_map_type::const_iterator const settings_group_iter = settings_r->find(settings_group);
|
||||||
|
|
||||||
llinfos << "Attempting to load settings for the group " << settings_group
|
llinfos << "Attempting to load settings for the group " << settings_group
|
||||||
<< " - from location " << location_key << llendl;
|
<< " - from location " << location_key << llendl;
|
||||||
|
|
||||||
if(gSettings.find(settings_group) == gSettings.end())
|
if(settings_group_iter == settings_r->end())
|
||||||
{
|
{
|
||||||
llwarns << "No matching settings group for name " << settings_group << llendl;
|
llwarns << "No matching settings group for name " << settings_group << llendl;
|
||||||
continue;
|
continue;
|
||||||
@@ -1624,11 +1630,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
|
|||||||
std::string custom_name_setting = file.get("NameFromSetting");
|
std::string custom_name_setting = file.get("NameFromSetting");
|
||||||
// *NOTE: Regardless of the group currently being lodaed,
|
// *NOTE: Regardless of the group currently being lodaed,
|
||||||
// this setting is always read from the Global settings.
|
// this setting is always read from the Global settings.
|
||||||
if(gSettings[sGlobalSettingsName]->controlExists(custom_name_setting))
|
LLControlGroup const* control_group = settings_r->find(sGlobalSettingsName)->second;
|
||||||
|
if(control_group->controlExists(custom_name_setting))
|
||||||
{
|
{
|
||||||
std::string file_name =
|
full_settings_path = control_group->getString(custom_name_setting);
|
||||||
gSettings[sGlobalSettingsName]->getString(custom_name_setting);
|
|
||||||
full_settings_path = file_name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1644,7 +1649,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
|
|||||||
requirement = file.get("Requirement").asInteger();
|
requirement = file.get("Requirement").asInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!gSettings[settings_group]->loadFromFile(full_settings_path, set_defaults))
|
if(!settings_group_iter->second->loadFromFile(full_settings_path, set_defaults))
|
||||||
{
|
{
|
||||||
if(requirement == 1)
|
if(requirement == 1)
|
||||||
{
|
{
|
||||||
@@ -1686,10 +1691,14 @@ std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
|
|||||||
|
|
||||||
bool LLAppViewer::initConfiguration()
|
bool LLAppViewer::initConfiguration()
|
||||||
{
|
{
|
||||||
|
// Grab and hold write locks for the entire duration of this function.
|
||||||
|
AIWriteAccess<settings_map_type> settings_w(gSettings);
|
||||||
|
settings_map_type& settings(*settings_w);
|
||||||
|
|
||||||
//Set up internal pointers
|
//Set up internal pointers
|
||||||
gSettings[sGlobalSettingsName] = &gSavedSettings;
|
settings[sGlobalSettingsName] = &gSavedSettings;
|
||||||
gSettings[sPerAccountSettingsName] = &gSavedPerAccountSettings;
|
settings[sPerAccountSettingsName] = &gSavedPerAccountSettings;
|
||||||
gSettings[sCrashSettingsName] = &gCrashSettings;
|
settings[sCrashSettingsName] = &gCrashSettings;
|
||||||
|
|
||||||
//Load settings files list
|
//Load settings files list
|
||||||
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
|
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
|
||||||
@@ -1714,7 +1723,7 @@ bool LLAppViewer::initConfiguration()
|
|||||||
|
|
||||||
// - load defaults
|
// - load defaults
|
||||||
bool set_defaults = true;
|
bool set_defaults = true;
|
||||||
if(!loadSettingsFromDirectory("Default", set_defaults))
|
if(!loadSettingsFromDirectory(settings_w, "Default", set_defaults))
|
||||||
{
|
{
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg << "Second Life could not load its default settings file. \n"
|
msg << "Second Life could not load its default settings file. \n"
|
||||||
@@ -1830,7 +1839,7 @@ bool LLAppViewer::initConfiguration()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// - load overrides from user_settings
|
// - load overrides from user_settings
|
||||||
loadSettingsFromDirectory("User");
|
loadSettingsFromDirectory(settings_w, "User");
|
||||||
|
|
||||||
// - apply command line settings
|
// - apply command line settings
|
||||||
clp.notify();
|
clp.notify();
|
||||||
@@ -1910,7 +1919,7 @@ bool LLAppViewer::initConfiguration()
|
|||||||
{
|
{
|
||||||
const std::string& name = *itr;
|
const std::string& name = *itr;
|
||||||
const std::string& value = *(++itr);
|
const std::string& value = *(++itr);
|
||||||
LLControlVariable* c = gSettings[sGlobalSettingsName]->getControl(name);
|
LLControlVariable* c = settings[sGlobalSettingsName]->getControl(name);
|
||||||
if(c)
|
if(c)
|
||||||
{
|
{
|
||||||
c->setValue(value, false);
|
c->setValue(value, false);
|
||||||
|
|||||||
@@ -33,7 +33,8 @@
|
|||||||
#ifndef LL_LLAPPVIEWER_H
|
#ifndef LL_LLAPPVIEWER_H
|
||||||
#define LL_LLAPPVIEWER_H
|
#define LL_LLAPPVIEWER_H
|
||||||
|
|
||||||
#include "llsys.h" // LLOSInfo
|
#include "llsys.h" // LLOSInfo
|
||||||
|
#include "llviewercontrol.h" // settings_map_type
|
||||||
|
|
||||||
class LLTextureCache;
|
class LLTextureCache;
|
||||||
class LLImageDecodeThread;
|
class LLImageDecodeThread;
|
||||||
@@ -140,11 +141,12 @@ public:
|
|||||||
// Load settings from the location specified by loction_key.
|
// Load settings from the location specified by loction_key.
|
||||||
// Key availale and rules for loading, are specified in
|
// Key availale and rules for loading, are specified in
|
||||||
// 'app_settings/settings_files.xml'
|
// 'app_settings/settings_files.xml'
|
||||||
bool loadSettingsFromDirectory(const std::string& location_key,
|
bool loadSettingsFromDirectory(AIReadAccess<settings_map_type> const& settings_r,
|
||||||
bool set_defaults = false);
|
std::string const& location_key,
|
||||||
|
bool set_defaults = false);
|
||||||
|
|
||||||
std::string getSettingsFilename(const std::string& location_key,
|
std::string getSettingsFilename(std::string const& location_key,
|
||||||
const std::string& file);
|
std::string const& file);
|
||||||
|
|
||||||
// For thread debugging.
|
// For thread debugging.
|
||||||
// llstartup needs to control init.
|
// llstartup needs to control init.
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ BOOL LLFloaterSettingsDebug::postBuild()
|
|||||||
void LLFloaterSettingsDebug::draw()
|
void LLFloaterSettingsDebug::draw()
|
||||||
{
|
{
|
||||||
LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
|
LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
|
||||||
LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
|
LLControlVariable* controlp = static_cast<LLControlVariable*>(settings_combo->getCurrentUserdata());
|
||||||
updateControl(controlp ? controlp->getCOAActive() : NULL);
|
updateControl(controlp ? controlp->getCOAActive() : NULL);
|
||||||
|
|
||||||
LLFloater::draw();
|
LLFloater::draw();
|
||||||
@@ -127,8 +127,8 @@ void LLFloaterSettingsDebug::show(void*)
|
|||||||
void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl, void* user_data)
|
void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl, void* user_data)
|
||||||
{
|
{
|
||||||
LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
|
LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
|
||||||
LLComboBox* combo_box = (LLComboBox*)ctrl;
|
LLComboBox* combo_box = static_cast<LLComboBox*>(ctrl);
|
||||||
LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata();
|
LLControlVariable* controlp = static_cast<LLControlVariable*>(combo_box->getCurrentUserdata());
|
||||||
|
|
||||||
floaterp->updateControl(controlp ? controlp->getCOAActive() : NULL);
|
floaterp->updateControl(controlp ? controlp->getCOAActive() : NULL);
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ void LLFloaterSettingsDebug::onCommitSettings(LLUICtrl* ctrl, void* user_data)
|
|||||||
LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
|
LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
|
||||||
|
|
||||||
LLComboBox* settings_combo = floaterp->getChild<LLComboBox>("settings_combo");
|
LLComboBox* settings_combo = floaterp->getChild<LLComboBox>("settings_combo");
|
||||||
LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
|
LLControlVariable* controlp = static_cast<LLControlVariable*>(settings_combo->getCurrentUserdata());
|
||||||
controlp = controlp ? controlp->getCOAActive() : NULL;
|
controlp = controlp ? controlp->getCOAActive() : NULL;
|
||||||
if(!controlp)//Uh oh!
|
if(!controlp)//Uh oh!
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -985,7 +985,7 @@ bool idle_startup()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Overwrite default user settings with user settings
|
// Overwrite default user settings with user settings
|
||||||
LLAppViewer::instance()->loadSettingsFromDirectory("Account");
|
LLAppViewer::instance()->loadSettingsFromDirectory(AIReadAccess<settings_map_type>(gSettings), "Account");
|
||||||
|
|
||||||
// Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
|
// Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
|
||||||
// and startup time is close enough if we don't have a real value.
|
// and startup time is close enough if we don't have a real value.
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
#include "llnetmap.h"
|
#include "llnetmap.h"
|
||||||
#include "llrender.h"
|
#include "llrender.h"
|
||||||
#include "llfloaterchat.h"
|
#include "llfloaterchat.h"
|
||||||
|
#include "aithreadsafe.h"
|
||||||
#include "llviewerobjectlist.h"
|
#include "llviewerobjectlist.h"
|
||||||
#include "lldrawpoolbump.h"
|
#include "lldrawpoolbump.h"
|
||||||
#include "emeraldboobutils.h"
|
#include "emeraldboobutils.h"
|
||||||
@@ -83,8 +84,7 @@
|
|||||||
BOOL gHackGodmode = FALSE;
|
BOOL gHackGodmode = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AITHREADSAFE(settings_map_type, gSettings,);
|
||||||
std::map<std::string, LLControlGroup*> gSettings;
|
|
||||||
LLControlGroup gSavedSettings; // saved at end of session
|
LLControlGroup gSavedSettings; // saved at end of session
|
||||||
LLControlGroup gSavedPerAccountSettings; // saved at end of session
|
LLControlGroup gSavedPerAccountSettings; // saved at end of session
|
||||||
LLControlGroup gColors; // read-only
|
LLControlGroup gColors; // read-only
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include "llcontrol.h"
|
#include "llcontrol.h"
|
||||||
#include "lluictrl.h"
|
#include "lluictrl.h"
|
||||||
|
#include "aithreadsafe.h"
|
||||||
|
|
||||||
// Enabled this definition to compile a 'hacked' viewer that
|
// Enabled this definition to compile a 'hacked' viewer that
|
||||||
// allows a hacked godmode to be toggled on and off.
|
// allows a hacked godmode to be toggled on and off.
|
||||||
@@ -48,7 +49,8 @@ extern BOOL gHackGodmode;
|
|||||||
//setting variables are declared in this function
|
//setting variables are declared in this function
|
||||||
void settings_setup_listeners();
|
void settings_setup_listeners();
|
||||||
|
|
||||||
extern std::map<std::string, LLControlGroup*> gSettings;
|
typedef std::map<std::string, LLControlGroup*> settings_map_type;
|
||||||
|
extern AIThreadSafe<settings_map_type> gSettings;
|
||||||
|
|
||||||
// for the graphics settings
|
// for the graphics settings
|
||||||
void create_graphics_group(LLControlGroup& group);
|
void create_graphics_group(LLControlGroup& group);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class LLControlGroupReader_Test : public LLControlGroupReader
|
|||||||
public:
|
public:
|
||||||
LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {}
|
LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {}
|
||||||
|
|
||||||
virtual std::string getString(const std::string& name)
|
virtual std::string getString(const std::string& name) const
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user