From 843036a7d27dbffa4aafeae70b3e46f9afe84c1b Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 6 Aug 2009 15:01:26 -0700 Subject: Fix for lllogin_tests crash on shutdown. RegisterFlush destructor was dereferencing a dangling reference to the mainloop EventPump which had already been destructed. --- indra/llcommon/llevents.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index c2fa79a524..aec9acc7ef 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -59,14 +59,12 @@ const char* queue_names[] = /***************************************************************************** * If there's a "mainloop" pump, listen on that to flush all LLEventQueues *****************************************************************************/ -struct RegisterFlush +struct RegisterFlush : public LLEventTrackable { RegisterFlush(): - pumps(LLEventPumps::instance()), - mainloop(pumps.obtain("mainloop")), - name("flushLLEventQueues") + pumps(LLEventPumps::instance()) { - mainloop.listen(name, boost::bind(&RegisterFlush::flush, this, _1)); + pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1)); } bool flush(const LLSD&) { @@ -75,11 +73,9 @@ struct RegisterFlush } ~RegisterFlush() { - mainloop.stopListening(name); + // LLEventTrackable handles stopListening for us. } LLEventPumps& pumps; - LLEventPump& mainloop; - const std::string name; }; static RegisterFlush registerFlush; -- cgit v1.2.3 From c9ee582c12bbdcfe7f37459f947872e3ef462560 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 6 Aug 2009 15:53:09 -0700 Subject: Add on-demand allocation of LLSingletonRegistry::sSingletonMap so we don't rely on static initialization order. reviewed by nat. --- indra/llcommon/llsingleton.cpp | 2 +- indra/llcommon/llsingleton.h | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 62988cdc64..6b5feaf1c4 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -34,5 +34,5 @@ #include "llsingleton.h" -std::map LLSingletonRegistry::sSingletonMap; +std::map * LLSingletonRegistry::sSingletonMap = NULL; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 00c87821c2..f55fafadd8 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -42,19 +42,30 @@ class LL_COMMON_API LLSingletonRegistry { private: typedef std::map TypeMap; - static TypeMap sSingletonMap; + static TypeMap * sSingletonMap; + + static void checkInit() + { + if(sSingletonMap == NULL) + { + sSingletonMap = new TypeMap(); + } + } public: template static void * & get() { std::string name(typeid(T).name()); - if(0 == sSingletonMap.count(name)) - { - sSingletonMap[name] = NULL; - } + checkInit(); + + // the first entry of the pair returned by insert will be either the existing + // iterator matching our key, or the newly inserted NULL initialized entry + // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html + TypeMap::iterator result = + sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first; - return sSingletonMap[typeid(T).name()]; + return result->second; } }; @@ -130,12 +141,13 @@ public: static SingletonInstanceData& getData() { - void * & registry = LLSingletonRegistry::get(); - static SingletonInstanceData data; + // this is static to cache the lookup results + static void * & registry = LLSingletonRegistry::get(); // *TODO - look into making this threadsafe if(NULL == registry) { + static SingletonInstanceData data; registry = &data; } -- cgit v1.2.3 From e6c9f944380d3a9b6562cf580e8c43a69c060dfd Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 6 Aug 2009 18:45:37 -0700 Subject: Backed out changeset bfb246df4655: rolling back LLFloaterTOS post-merge fixups because they didn't work on linux. --- indra/newview/llfloatertos.cpp | 7 +------ indra/newview/llfloatertos.h | 3 --- indra/newview/lllogininstance.cpp | 18 ++++++++---------- indra/newview/tests/lllogininstance_test.cpp | 24 ++++++++---------------- 4 files changed, 17 insertions(+), 35 deletions(-) diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 9859d34284..40bd6360ed 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -57,7 +57,7 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& message) mMessage(message.asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback() + mCallback(callback) { } @@ -240,8 +240,3 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) tos_agreement->setEnabled( true ); }; } - -void LLFloaterTOS::setTOSCallback(LLFloaterTOS::YesNoCallback const & callback) -{ - mCallback = callback; -} diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0b15c24bc8..0be440d92b 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -66,9 +66,6 @@ public: virtual void onNavigateComplete( const EventType& eventIn ); - // *TODO - consider getting rid of this in favor of using an event pump. -brad - void setTOSCallback(YesNoCallback const & callback); - private: std::string mMessage; int mWebBrowserWindowId; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 3c59cb83cd..f967fcaf97 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -49,7 +49,6 @@ #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llurlsimstring.h" -#include "llfloaterreg.h" #include "llfloatertos.h" #include "llwindow.h" #if LL_LINUX || LL_SOLARIS @@ -222,19 +221,18 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_tos", LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, + LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_critical",LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical")); + LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, + message_response, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical") + ); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index d3080d6e4a..5af8acebaf 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -91,23 +91,15 @@ LLURLSimString LLURLSimString::sInstance; bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- -#include "llfloaterreg.h" #include "../llfloatertos.h" -static std::string gTOSType; +static LLFloaterTOS::ETOSType gTOSType; static LLFloaterTOS::YesNoCallback gTOSCallback; - -void LLFloaterTOS::setTOSCallback(YesNoCallback const & callback) +LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, + const std::string & message, + const YesNoCallback& callback) { + gTOSType = type; gTOSCallback = callback; -} - -//static -LLFloater* LLFloaterReg::showInstance(const std::string & name, - const LLSD & key, - BOOL focus) -{ - gTOSType = name; - gTOSCallback = LLFloaterTOS::YesNoCallback(); return NULL; } @@ -190,7 +182,7 @@ namespace tut gLoginCreds.clear(); gDisconnectCalled = false; - gTOSType = ""; // Set to invalid value. + // gTOSType = -1; // Set to invalid value. gTOSCallback = 0; // clear the callback. @@ -279,7 +271,7 @@ namespace tut response["data"]["reason"] = "tos"; gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, "message_tos"); + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); @@ -305,7 +297,7 @@ namespace tut response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, "message_critical"); + ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); ensure("TOS callback given", gTOSCallback != 0); gTOSCallback(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); -- cgit v1.2.3 From 8f4811f3fd7f252a5f5bc50ed11fecd8e42f3e68 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 11 Aug 2009 12:09:18 -0400 Subject: Better solution for fixing up the LLFloaterTOS callback after the last viewer-2.0.0-3 merge. LLFloaterTOS and LLLoginInstance now communicate through an event pump "lllogininstance_tos_callback". reviewed by Mani. --- indra/newview/llfloatertos.cpp | 17 +++++------ indra/newview/llfloatertos.h | 6 ++-- indra/newview/lllogininstance.cpp | 42 ++++++++++++++++------------ indra/newview/lllogininstance.h | 2 +- indra/newview/tests/lllogininstance_test.cpp | 33 +++++++++++----------- 5 files changed, 53 insertions(+), 47 deletions(-) diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 11f35bedad..e43c3ecde7 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -52,12 +52,12 @@ #include "message.h" -LLFloaterTOS::LLFloaterTOS(const LLSD& message) -: LLModalDialog( message, 100, 100 ), - mMessage(message.asString()), +LLFloaterTOS::LLFloaterTOS(const LLSD& data) +: LLModalDialog( data["message"].asString(), 100, 100 ), + mMessage(data["message"].asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback() + mReplyPumpName(data["reply_pump"].asString()) { } @@ -205,9 +205,9 @@ void LLFloaterTOS::onContinue( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User agrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(true); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true)); } self->closeFloater(); // destroys this object @@ -219,9 +219,9 @@ void LLFloaterTOS::onCancel( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User disagrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(false); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false)); } self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS @@ -240,3 +240,4 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) tos_agreement->setEnabled( true ); }; } + diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0be440d92b..89ad29170c 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -49,11 +49,9 @@ class LLFloaterTOS : public LLWebBrowserCtrlObserver { public: - LLFloaterTOS(const LLSD& message); + LLFloaterTOS(const LLSD& data); virtual ~LLFloaterTOS(); - typedef boost::function YesNoCallback; - BOOL postBuild(); virtual void draw(); @@ -70,7 +68,7 @@ private: std::string mMessage; int mWebBrowserWindowId; int mLoadCompleteCount; - YesNoCallback mCallback; + std::string mReplyPumpName; }; #endif // LL_LLFLOATERTOS_H diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 428bed7b72..cb7dbc2de0 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -56,6 +56,9 @@ #include "lltrans.h" #endif +static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; +static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; + std::string construct_start_string(); LLLoginInstance::LLLoginInstance() : @@ -222,26 +225,25 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_tos", LLSD(message_response)); - /* - LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "agree_to_tos")); - */ + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_tos", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance("message_critical",LLSD(message_response)); - /* - LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, - message_response, - boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical") - ); - */ + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_critical", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical")); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { @@ -286,7 +288,7 @@ bool LLLoginInstance::handleLoginSuccess(const LLSD& event) return false; } -void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) +bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { if(accepted) { @@ -298,6 +300,9 @@ void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { attemptComplete(); } + + LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); + return true; } @@ -460,3 +465,4 @@ std::string construct_start_string() } return start; } + diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 47d52a6184..6a2ccf919e 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -88,7 +88,7 @@ private: bool handleLoginFailure(const LLSD& event); bool handleLoginSuccess(const LLSD& event); - void handleTOSResponse(bool v, const std::string& key); + bool handleTOSResponse(bool v, const std::string& key); void attemptComplete() { mAttemptComplete = true; } // In the future an event? diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 5af8acebaf..a84e796159 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -92,14 +92,15 @@ bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- #include "../llfloatertos.h" -static LLFloaterTOS::ETOSType gTOSType; -static LLFloaterTOS::YesNoCallback gTOSCallback; -LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type, - const std::string & message, - const YesNoCallback& callback) +#include "llfloaterreg.h" +static std::string gTOSType; +static LLEventPump * gTOSReplyPump = NULL; + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) { - gTOSType = type; - gTOSCallback = callback; + gTOSType = name; + gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]); return NULL; } @@ -182,8 +183,8 @@ namespace tut gLoginCreds.clear(); gDisconnectCalled = false; - // gTOSType = -1; // Set to invalid value. - gTOSCallback = 0; // clear the callback. + gTOSType = ""; // Set to invalid value. + gTOSReplyPump = 0; // clear the callback. gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); @@ -271,15 +272,15 @@ namespace tut response["data"]["reason"] = "tos"; gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(false); // Call callback denying TOS. + ensure_equals("TOS Dialog type", gTOSType, "message_tos"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); // Start again. logininstance->connect(test_uri, credentials); gTestPump.post(response); // Fail for tos again. - gTOSCallback(true); // Accept tos, should reconnect w/ agree_to_tos. + gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); @@ -297,9 +298,9 @@ namespace tut response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); - ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(true); + ensure_equals("TOS Dialog type", gTOSType, "message_critical"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); -- cgit v1.2.3