Commits

Merov Linden  committed 879ad46 Merge

STORM-670 : merges fixes for CHOP-220 and CHOP-221

  • Participants
  • Parent commits 5dd845f, e30b20e

Comments (0)

Files changed (9)

File indra/llcommon/llthread.cpp

 {
 	LLThread *threadp = (LLThread *)datap;
 
-	// Set thread state to running
-	threadp->mStatus = RUNNING;
-
 	// Run the user supplied function
 	threadp->run();
 
 
 void LLThread::start()
 {
-	apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);	
+	llassert(isStopped());
+	
+	// Set thread state to running
+	mStatus = RUNNING;
 
-	// We won't bother joining
-	apr_thread_detach(mAPRThreadp);
+	apr_status_t status =
+		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
+	
+	if(status == APR_SUCCESS)
+	{	
+		// We won't bother joining
+		apr_thread_detach(mAPRThreadp);
+	}
+	else
+	{
+		mStatus = STOPPED;
+		llwarns << "failed to start thread " << mName << llendl;
+		ll_apr_warn_status(status);
+	}
 }
 
 //============================================================================

File indra/newview/CMakeLists.txt

     lldateutil.cpp
     llmediadataclient.cpp
     lllogininstance.cpp
+    llremoteparcelrequest.cpp
     llviewerhelputil.cpp
     llversioninfo.cpp
   )

File indra/newview/llagent.h

 #include "llagentconstants.h"
 #include "llagentdata.h" 			// gAgentID, gAgentSessionID
 #include "llcharacter.h" 			// LLAnimPauseRequest
+#include "llcoordframe.h"			// for mFrameAgent
 #include "llpointer.h"
 #include "lluicolor.h"
 #include "llvoavatardefines.h"

File indra/newview/llpanellandmarks.cpp

 {
 	if (!parcel_id.isNull())
 	{
-        //ext-4655, defensive. remove now incase this gets called twice without a remove
-        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_id, this);
-        
 		LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
 		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
 	}

File indra/newview/llpanelpick.cpp

 {
 	if (mParcelId != mRequestedId)
 	{
-        //ext-4655, remove now incase this gets called twice without a remove
-        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedId, this);
-        
 		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this);
 		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId);
 

File indra/newview/llpanelplaceinfo.cpp

 {
 	if (mParcelID != mRequestedID)
 	{
-        //ext-4655, defensive. remove now incase this gets called twice without a remove
-        //as panel never closes its ok atm (but wrong :) 
-        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedID, this);
-
 		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
 		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
 

File indra/newview/llremoteparcelrequest.cpp

 
 void LLRemoteParcelInfoProcessor::addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
 {
+	observer_multimap_t::iterator it;
+	observer_multimap_t::iterator end = mObservers.upper_bound(parcel_id);
+
 	// Check if the observer is already in observers list for this UUID
-	observer_multimap_t::iterator it;
-
-	it = mObservers.find(parcel_id);
-	while (it != mObservers.end())
+	for(it = mObservers.find(parcel_id); it != end; ++it)
 	{
-		if (it->second == observer)
+		if (it->second.get() == observer)
 		{
 			return;
 		}
-		else
-		{
-			++it;
-		}
 	}
 
-	mObservers.insert(std::pair<LLUUID, LLRemoteParcelInfoObserver*>(parcel_id, observer));
+	mObservers.insert(std::make_pair(parcel_id, observer->getObserverHandle()));
 }
 
 void LLRemoteParcelInfoProcessor::removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
 	}
 
 	observer_multimap_t::iterator it;
+	observer_multimap_t::iterator end = mObservers.upper_bound(parcel_id);
 
-	it = mObservers.find(parcel_id);
-	while (it != mObservers.end())
+	for(it = mObservers.find(parcel_id); it != end; ++it)
 	{
-		if (it->second == observer)
+		if (it->second.get() == observer)
 		{
 			mObservers.erase(it);
 			break;
 		}
-		else
-		{
-			++it;
-		}
 	}
 }
 
 	msg->getS32		("Data", "SalePrice", parcel_data.sale_price);
 	msg->getS32		("Data", "AuctionID", parcel_data.auction_id);
 
-	LLRemoteParcelInfoProcessor::observer_multimap_t observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
+	LLRemoteParcelInfoProcessor::observer_multimap_t & observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
 
-	observer_multimap_t::iterator oi = observers.find(parcel_data.parcel_id);
+	typedef std::vector<observer_multimap_t::iterator> deadlist_t;
+	deadlist_t dead_iters;
+
+	observer_multimap_t::iterator oi;
 	observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
-	for (; oi != end; ++oi)
+
+	for (oi = observers.find(parcel_data.parcel_id); oi != end; ++oi)
 	{
-		oi->second->processParcelInfo(parcel_data);
+		LLRemoteParcelInfoObserver * observer = oi->second.get();
+		if(observer)
+		{
+			observer->processParcelInfo(parcel_data);
+		}
+		else
+		{
+			// the handle points to an expired observer, so don't keep it
+			// around anymore
+			dead_iters.push_back(oi);
+		}
+	}
+
+	deadlist_t::iterator i;
+	deadlist_t::iterator end_dead = dead_iters.end();
+	for(i = dead_iters.begin(); i != end_dead; ++i)
+	{
+		observers.erase(*i);
 	}
 }
 

File indra/newview/llremoteparcelrequest.h

 	static void processParcelInfoReply(LLMessageSystem* msg, void**);
 
 private:
-	typedef std::multimap<LLUUID, LLRemoteParcelInfoObserver*> observer_multimap_t;
+	typedef std::multimap<LLUUID, LLHandle<LLRemoteParcelInfoObserver> > observer_multimap_t;
 	observer_multimap_t mObservers;
 };
 

File indra/newview/tests/llremoteparcelrequest_test.cpp

+/** 
+ * @file llremoteparcelrequest_test.cpp
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llremoteparcelrequest.h"
+
+#include "../llagent.h"
+#include "message.h"
+
+namespace {
+	LLControlGroup s_saved_settings("dummy_settings");
+	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
+}
+
+LLCurl::Responder::Responder() { }
+LLCurl::Responder::~Responder() { }
+void LLCurl::Responder::error(U32,std::string const &) { }
+void LLCurl::Responder::result(LLSD const &) { }
+void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
+void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
+void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
+void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
+void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
+void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
+void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
+void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { }
+void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32)
+{
+	out_id = TEST_PARCEL_ID;
+}
+void LLMessageSystem::nextBlock(char const *) { }
+void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
+void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
+void LLMessageSystem::nextBlockFast(char const *) { }
+void LLMessageSystem::newMessage(char const *) { }
+LLMessageSystem * gMessageSystem;
+char * _PREHASH_AgentID;
+char * _PREHASH_AgentData;
+LLAgent gAgent;
+LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { }
+LLAgent::~LLAgent() { }
+void LLAgent::sendReliableMessage(void) { }
+LLUUID gAgentSessionID;
+LLUUID gAgentID;
+LLUIColor::LLUIColor(void) { }
+LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
+LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
+LLControlGroup::~LLControlGroup(void) { }
+
+namespace tut
+{
+	struct TestObserver : public LLRemoteParcelInfoObserver {
+		TestObserver() : mProcessed(false) { }
+
+		virtual void processParcelInfo(const LLParcelData& parcel_data)
+		{
+			mProcessed = true;
+		}
+
+		virtual void setParcelID(const LLUUID& parcel_id) { }
+
+		virtual void setErrorStatus(U32 status, const std::string& reason) { }
+
+		bool mProcessed;
+	};
+
+    struct RemoteParcelRequestData
+    {
+		RemoteParcelRequestData()
+		{
+		}
+    };
+    
+	typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t;
+	typedef remoteparcelrequest_t::object remoteparcelrequest_object_t;
+	tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest");
+
+	template<> template<>
+	void remoteparcelrequest_object_t::test<1>()
+	{
+		set_test_name("observer pointer");
+
+		boost::scoped_ptr<TestObserver> observer(new TestObserver());
+
+		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
+		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get());
+
+		processor.processParcelInfoReply(gMessageSystem, NULL);
+
+		ensure(observer->mProcessed);
+	}
+
+	template<> template<>
+	void remoteparcelrequest_object_t::test<2>()
+	{
+		set_test_name("CHOP-220: dangling observer pointer");
+
+		LLRemoteParcelInfoObserver * observer = new TestObserver();
+
+		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
+		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer);
+
+		delete observer;
+		observer = NULL;
+
+		processor.processParcelInfoReply(gMessageSystem, NULL);
+	}
+}