Scott Lawrence avatar Scott Lawrence committed 1298a49 Merge

merge changes for DRTVWR-238

Comments (0)

Files changed (25)

 0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
 710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
 2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
+f7bedce18ad52283e6072814db23318907261487 DRTVWR-238

indra/llcharacter/lleditingmotion.cpp

 	target = target * target_dist;
 	if (!target.isFinite())
 	{
-		llerrs << "Non finite target in editing motion with target distance of " << target_dist << 
+		// Don't error out here, set a fail-safe target vector
+		llwarns << "Non finite target in editing motion with target distance of " << target_dist << 
 			" and focus point " << focus_pt << llendl;
+		target.setVec(1.f, 1.f, 1.f);
 	}
 	
 	mTarget.setPosition( target + mParentJoint.getPosition());

indra/llcommon/llstring.cpp

 
 std::string ll_safe_string(const char* in, S32 maxlen)
 {
-	if(in) return std::string(in, maxlen);
+	if(in && maxlen > 0 ) return std::string(in, maxlen);
+
 	return std::string();
 }
 

indra/llrender/llgl.h

 class LLGLFence
 {
 public:
+	virtual ~LLGLFence()
+	{
+	}
+
 	virtual void placeFence() = 0;
 	virtual bool isCompleted() = 0;
 	virtual void wait() = 0;

indra/llrender/llrendertarget.cpp

 	}
 
 	U32 offset = mTex.size();
-	if (offset >= 4 ||
-		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
+
+	if( offset >= 4 )
 	{
-		llerrs << "Too many color attachments!" << llendl;
+		llwarns << "Too many color attachments" << llendl;
+		llassert( offset < 4 );
+		return false;
+	}
+	if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) )
+	{
+		llwarns << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << llendl;
+		llassert(  mFBO != 0 );
+		llassert( gGLManager.mHasDrawBuffers );
+		return false;
 	}
 
 	U32 tex;

indra/llrender/llvertexbuffer.cpp

 	gGL.syncMatrices();
 
 	U32 count = pos.size();
-	llassert_always(norm.size() >= pos.size());
-	llassert_always(count > 0);
+	
+	llassert(norm.size() >= pos.size());
+	llassert(count > 0);
+
+	if( count == 0 )
+	{
+		llwarns << "Called drawArrays with 0 vertices" << llendl;
+		return;
+	}
+
+	if( norm.size() < pos.size() )
+	{
+		llwarns << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << llendl;
+		return;
+	}
 
 	unbind();
 	

indra/newview/llagent.cpp

 void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
 {
 	LLViewerRegion* regionp = getRegion();
+
+	if (!regionp)
+	{
+		return;
+	}
+
 	U64 handle = to_region_handle(pos_global);
 	LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
 	if(regionp && info)

indra/newview/llappearancemgr.cpp

 
 std::string self_av_string()
 {
-	return gAgentAvatarp->avString();
+	// On logout gAgentAvatarp can already be invalid
+	return isAgentAvatarValid() ? gAgentAvatarp->avString() : "";
 }
 
 // RAII thingy to guarantee that a variable gets reset when the Setter

indra/newview/llattachmentsmgr.cpp

 
 void LLAttachmentsMgr::onIdle()
 {
+	// Make sure we got a region before trying anything else
+	if( !gAgent.getRegion() )
+	{
+		return;
+	}
+
 	S32 obj_count = mPendingAttachments.size();
 	if (obj_count == 0)
 	{

indra/newview/lldrawpoolwlsky.cpp

 	bool error;
 	LLColor4 star_alpha(LLColor4::black);
 	star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f;
-	llassert_always(!error);
+
+	// If start_brightness is not set, exit
+	if( error )
+	{
+		llwarns << "star_brightness missing in mCurParams" << llendl;
+		return;
+	}
 
 	gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex());
 
 	gGL.pushMatrix();
 	gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
-	// gl_FragColor.rgb = gl_Color.rgb;
-	// gl_FragColor.a = gl_Color.a * star_alpha.a;
 	if (LLGLSLShader::sNoFixedFunction)
 	{
 		gCustomAlphaProgram.bind();

indra/newview/llface.cpp

 	}
 
 	const LLTextureEntry* te = getTextureEntry();
-
+	if( !te || !getViewerObject() || !getTexture() )
+	{
+		return false;
+	}
+	
 	if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha
 		(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask
 		getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive)

indra/newview/llfloaterbvhpreview.cpp

 	LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
 	BOOL paused = avatarp->areAnimationsPaused();
 
-	// *TODO: Fix awful casting hack
-	LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
-	
-	// Set emotion
-	std::string emote = getChild<LLUICtrl>("emote_combo")->getValue().asString();
-	motionp->setEmote(mIDList[emote]);
-	
+	LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*>(avatarp->findMotion(mMotionID));
+	if( motionp )
+	{
+		// Set emotion
+		std::string emote = getChild<LLUICtrl>("emote_combo")->getValue().asString();
+		motionp->setEmote(mIDList[emote]);
+	}
+
 	LLUUID base_id = mIDList[getChild<LLUICtrl>("preview_base_anim")->getValue().asString()];
 	avatarp->deactivateAllMotions();
 	avatarp->startMotion(mMotionID, 0.0f);
 	// Set pose
 	std::string handpose = getChild<LLUICtrl>("hand_pose_combo")->getValue().asString();
 	avatarp->startMotion( ANIM_AGENT_HAND_MOTION, 0.0f );
-	motionp->setHandPose(LLHandMotion::getHandPose(handpose));
 
+	if( motionp )
+	{
+		motionp->setHandPose(LLHandMotion::getHandPose(handpose));
+	}
+	
 	if (paused)
 	{
 		mPauseRequest = avatarp->requestPause();

indra/newview/llinventorybridge.cpp

 		LLInventoryModel::item_array_t* item_array;
 		gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array);
 
-		S32 item_count = item_array->count();
-		S32 cat_count = cat_array->count();
-	
+		S32 item_count(0);
+		if( item_array )
+		{			
+			item_count = item_array->count();
+		}
+		
+		S32 cat_count(0);
+		if( cat_array )
+		{			
+			cat_count = cat_array->count();
+		}
+
 		// Move to next if current folder empty
 		if ((item_count == 0) && (cat_count == 0))
-	{
+		{
 			continue;
-	}
+		}
 
 		uuid_vec_t ids;
 		LLRightClickInventoryFetchObserver* outfit = NULL;

indra/newview/llmeshrepository.cpp

 			mMeshHeader[mesh_id] = header;
 			}
 
+
+		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
+
 		//check for pending requests
 		pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
 		if (iter != mPendingLOD.end())
 		{
-			LLMutexLock lock(mMutex);
 			for (U32 i = 0; i < iter->second.size(); ++i)
 			{
 				LODRequest req(mesh_params, iter->second[i]);
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
-
+	// thread could have already be destroyed during logout
+	if( !gMeshRepo.mThread )
+	{
+		return;
+	}
+	
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
 	if (status < 200 || status > 400)
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
+	// thread could have already be destroyed during logout
+	if( !gMeshRepo.mThread )
+	{
+		return;
+	}
+
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
 	if (status < 200 || status > 400)
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
+	if( !gMeshRepo.mThread )
+	{
+		return;
+	}
+
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
 	if (status < 200 || status > 400)
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
+	// thread could have already be destroyed during logout
+	if( !gMeshRepo.mThread )
+	{
+		return;
+	}
+
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
 	if (status < 200 || status > 400)
 							  const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 {
+	// thread could have already be destroyed during logout
+	if( !gMeshRepo.mThread )
+	{
+		return;
+	}
+
 	if (status < 200 || status > 400)
 	{
 		//llwarns

indra/newview/llnotificationmanager.cpp

 {
 	LLSysHandler* handle = NULL;
 
+	// Don't bother if we're going down.
+	// Otherwise we might crash when trying to use handlers that are already dead.
+	if( LLApp::isExiting() )
+	{
+		return false;
+	}
+
 	if (LLNotifications::destroyed())
 		return false;
 

indra/newview/llpaneleditwearable.cpp

         BOOL isDirty = FALSE;
         if (mWearablePtr)
         {
-                if (mWearablePtr->isDirty() ||
-                        mWearableItem->getName().compare(mNameEditor->getText()) != 0)
-                {
-                        isDirty = TRUE;
-                }
+			if (mWearablePtr->isDirty() ||
+				( mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0 ))
+			{
+				isDirty = TRUE;
+			}
         }
         return isDirty;
 }

indra/newview/llpreview.cpp

 
 void LLMultiPreview::onOpen(const LLSD& key)
 {
-	LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
+	// Floater could be something else than LLPreview, eg LLFloaterProfile.
+	LLPreview* frontmost_preview = dynamic_cast<LLPreview*>(mTabContainer->getCurrentPanel());
+
 	if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
 	{
 		frontmost_preview->loadAsset();
 {
 	if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
 	{
-		LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
-		if (frontmost_preview) frontmost_preview->userResized();
+		// Floater could be something else than LLPreview, eg LLFloaterProfile.
+		LLPreview* frontmost_preview = dynamic_cast<LLPreview*>(mTabContainer->getCurrentPanel());
+
+		if (frontmost_preview)
+		{
+			frontmost_preview->userResized();
+		}
 	}
 	LLFloater::handleReshape(new_rect, by_user);
 }
 
 void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
 {
-	LLPreview* opened_preview = (LLPreview*)opened_floater;
+	// Floater could be something else than LLPreview, eg LLFloaterProfile.
+	LLPreview* opened_preview = dynamic_cast<LLPreview*>(opened_floater);
+
 	if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
 	{
 		opened_preview->loadAsset();

indra/newview/llscreenchannel.cpp

 
 	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
 
-	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+	// Use a local variable instead of mToastList.
+	// mToastList can be modified during recursive calls and then all iteratos will be invalidated.
+	std::vector<ToastElem> vToastList( mToastList );
+
+	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)
 	{
-		if(it != mToastList.rbegin())
+		if(it != vToastList.rbegin())
 		{
 			LLToast* toast = (it-1)->getToast();
 			if (!toast)
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = floater->getRect().getHeight();
 
 		if(!stop_showing_toasts)
 		{
-			if( it != mToastList.rend()-1)
+			if( it != vToastList.rend()-1)
 			{
 				S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
 				stop_showing_toasts = toast_top > getRect().mTop;
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
 	}
 
 	// Dismiss toasts we don't have space for (STORM-391).
-	if(it != mToastList.rend())
+	if(it != vToastList.rend())
 	{
 		mHiddenToastsNum = 0;
-		for(; it != mToastList.rend(); it++)
+
+		for(; it != vToastList.rend(); it++)
 		{
 			LLToast* toast = it->getToast();
 			if (toast)
 
 	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
 
-	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+	// Use a local variable instead of mToastList.
+	// mToastList can be modified during recursive calls and then all iteratos will be invalidated.
+	std::vector<ToastElem> vToastList( mToastList );
+
+	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)
 	{
-		if(it != mToastList.rbegin())
+		if(it != vToastList.rbegin())
 		{
 			LLToast* toast = (it-1)->getToast();
 			if (!toast)
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = -floater->getRect().getHeight();
 
 		if(!stop_showing_toasts)
 		{
-			if( it != mToastList.rend()-1)
+			if( it != vToastList.rend()-1)
 			{
 				S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");
 				stop_showing_toasts = toast_bottom < channel_rect.mBottom;
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
 
 	// Dismiss toasts we don't have space for (STORM-391).
 	std::vector<LLToast*> toasts_to_hide;
-	if(it != mToastList.rend())
+
+	if(it != vToastList.rend())
 	{
 		mHiddenToastsNum = 0;
-		for(; it != mToastList.rend(); it++)
+
+		for(; it != vToastList.rend(); it++)
 		{
 			LLToast* toast = it->getToast();
 			if (toast)

indra/newview/llviewertexture.cpp

 	for(U32 i = 0 ; i < mNumFaces ; i++)
 	{				
 		LLFace* facep = mFaceList[i] ;
-		if(facep->getDrawable()->isRecentlyVisible())
+		if( facep && facep->getDrawable() && facep->getDrawable()->isRecentlyVisible())
 		{
 			addTextureStats(facep->getVirtualSize()) ;
 			setAdditionalDecodePriority(facep->getImportanceToCamera()) ;

indra/newview/llvoavatar.cpp

 		}
 		// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
 		// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
-		if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
+
+		if ( getImage(TEX_HAIR_BAKED, 0)
+			&& getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
 		{
 			num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);
 			first_pass = FALSE;
 		LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index);
 		U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
 		const LLTextureEntry *te = getTE(texture_index);
-		const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
+
+		// getTE can return 0.
+		// Not sure yet why it does, but of course it crashes when te->mScale? gets used.
+		// Put safeguard in place so this corner case get better handling and does not result in a crash.
+		F32 texel_area_ratio = 1.0f;
+		if( te )
+		{
+			texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
+		}
+		else
+		{
+			llwarns << "getTE( " << texture_index << " ) returned 0" <<llendl;
+		}
+
 		LLViewerFetchedTexture *imagep = NULL;
 		for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)
 		{
 		return FALSE;
 	}
 
+	if( !getImage( te, index ) )
+	{
+		llwarns << "getImage( " << te << ", " << index << " ) returned 0" << llendl;
+		return FALSE;
+	}
+
 	return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR && 
 			getImage(te, index)->getID() != IMG_DEFAULT);
 }

indra/newview/llvovolume.cpp

 	if (mDrawable->isState(LLDrawable::RIGGED))
 	{
 		LLVOAvatar* avatar = getAvatar(); 
+		
+		// Not sure how this can really happen, but alas it does. Better exit here than crashing.
+		if( !avatar || !avatar->mDrawable )
+		{
+			return FALSE;
+		}
+
 		distance = avatar->mDrawable->mDistanceWRTCamera;
 		radius = avatar->getBinRadius();
 	}
 
 void LLVOVolume::updateFaceFlags()
 {
-	for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
+	// There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces()
+	for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++)
 	{
 		LLFace *face = mDrawable->getFace(i);
 		if (face)
 		volume = getVolume();
 	}
 
-	for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)
+	// There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces()
+	for (S32 i = 0;
+		 i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs();
+		 i++)
 	{
 		LLFace *face = mDrawable->getFace(i);
 		if (!face)
 
 void LLVOVolume::updateFaceSize(S32 idx)
 {
+	if( mDrawable->getNumFaces() <= idx )
+	{
+		return;
+	}
+
 	LLFace* facep = mDrawable->getFace(idx);
 	if (facep)
 	{
 	//add the face to show the media if it is in playing
 	if(mDrawable)
 	{
-		LLFace* facep = mDrawable->getFace(texture_index) ;
+		LLFace* facep(NULL);
+		if( texture_index < mDrawable->getNumFaces() )
+		{
+			facep = mDrawable->getFace(texture_index) ;
+		}
+
 		if(facep)
 		{
 			LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
 
 			LLVector4a* pos = dst_face.mPositions;
 
+			if( pos && weight && dst_face.mExtents )
 			{
 				LLFastTimer t(FTM_SKIN_RIGGED);
 

indra/newview/llwlhandlers.cpp

 		return;
 	}
 
-	if (unvalidated_content[0]["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
+	LLUUID regionId;
+	if( gAgent.getRegion() )
+	{
+		regionId = gAgent.getRegion()->getRegionID();
+	}
+	
+	if (unvalidated_content[0]["regionID"].asUUID() != regionId )
 	{
 		LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
-			<< gAgent.getRegion()->getRegionID() << " but got " << unvalidated_content[0]["regionID"].asUUID()
+			<< regionId << " but got " << unvalidated_content[0]["regionID"].asUUID()
 			<< ") - ignoring..." << LL_ENDL;
 		return;
 	}

indra/newview/pipeline.cpp

 void LLPipeline::clearReferences()
 {
 	sCull = NULL;
+	mGroupSaveQ1.clear();
 }
 
 void check_references(LLSpatialGroup* group, LLDrawable* drawable)
 		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
 	}
 
+	mGroupSaveQ1 = mGroupQ1;
 	mGroupQ1.clear();
 	mGroupQ1Locked = false;
 

indra/newview/pipeline.h

 	LLSpatialGroup::sg_vector_t		mGroupQ1; //priority
 	LLSpatialGroup::sg_vector_t		mGroupQ2; // non-priority
 
+	LLSpatialGroup::sg_vector_t		mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref
+
 	LLSpatialGroup::sg_vector_t		mMeshDirtyGroup; //groups that need rebuildMesh called
 	U32 mMeshDirtyQueryObject;
 

indra/viewer_components/login/lllogin.cpp

             }
             return;             // Done!
         }
+
+		/* Sometimes we end with "Started" here. Slightly slow server?
+		 * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+		 */
+		if( status == "Started")
+		{
+			LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+			continue;
+		}
+
         // If we don't recognize status at all, trouble
         if (! (status == "CURLError"
                || status == "XMLRPCError"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.