diff --git a/.hgtags b/.hgtags
index 25bf70c6c61116a050f7ac54b90d0db9164db96d..7e1c0d2a0b02bc1bb2e50ef4073441c46a5498ed 100755
--- a/.hgtags
+++ b/.hgtags
@@ -354,3 +354,4 @@ e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2
 0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
 710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
 2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
+f7bedce18ad52283e6072814db23318907261487 DRTVWR-238
diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp
index 66b3c2bd25f15196ac8f23e5e88527a175f9143d..0d0b85ba60480ff4a1c61c7f3c4a416bfd3790b4 100644
--- a/indra/llcharacter/lleditingmotion.cpp
+++ b/indra/llcharacter/lleditingmotion.cpp
@@ -214,8 +214,10 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
 	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());
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index fa0eb9f72c7a501b92bf26d6c2accc25d9993138..0c326797449792f1d6138abba8e7947c3f4a7e11 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -47,7 +47,8 @@ std::string ll_safe_string(const char* in)
 
 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();
 }
 
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 964495a3abce301eae301d196b1e3d917d0820db..d70e764769a12e7854939dc36bf3d1071a5b34c4 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -424,6 +424,10 @@ const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000;  //1 ms
 class LLGLFence
 {
 public:
+	virtual ~LLGLFence()
+	{
+	}
+
 	virtual void placeFence() = 0;
 	virtual bool isCompleted() = 0;
 	virtual void wait() = 0;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index cc5c2323809b40c43b79f843fe19fbd0997558e2..846311a8d045cf459ede3a0e9c22ea7596c68671 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -163,10 +163,19 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
 	}
 
 	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;
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index eadef93c890f871634b8ee1061d560f2d19c2f7e..2fe0aa0b725491fdcd62896bd456e2cad4895ec1 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -555,8 +555,21 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con
 	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();
 	
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 447836910d2044400e742d7b1cf75db882702f04..11fa50b51a7f93e23c5a3a3f6d1ecb2424cceb09 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4045,6 +4045,12 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
 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)
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 6d67e098a615d48556304671f1777eb6687c867c..06a9892c7e2f09eed17cea5e7bd91c0b15eba8aa 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -52,7 +52,8 @@
 
 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
diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp
index c9543988a68b212751730df554946ac92bf3074b..ea0b8f00a4342f63e68b7f104e6beee32625e188 100644
--- a/indra/newview/llattachmentsmgr.cpp
+++ b/indra/newview/llattachmentsmgr.cpp
@@ -62,6 +62,12 @@ void LLAttachmentsMgr::onIdle(void *)
 
 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)
 	{
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index caf15fe1cbb0616719f98e98b7989980ad2c9f38..b5faff7968215f467aabb38a2e2da8a3b674ca6f 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -192,14 +192,18 @@ void LLDrawPoolWLSky::renderStars(void) const
 	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();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 188f943f136d53d2c8dbfb6e1688ed3f55905da6..605cb81c103b99d221d785c90356b9cd10b15f42 100755
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1062,7 +1062,11 @@ bool LLFace::canRenderAsMask()
 	}
 
 	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)
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index fa0ad20fdb09a310f5170f68f0513f321cc4e83c..62848586cdbb1438589b502fc5312f18e2d0c8d4 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -422,13 +422,14 @@ void LLFloaterBvhPreview::resetMotion()
 	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);
@@ -438,8 +439,12 @@ void LLFloaterBvhPreview::resetMotion()
 	// 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();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index fce0b7c9c92ebe0a4a6eb16e510d17fdeb596f62..14a228df1cb91a062c068ebb07567f29d60e8be9 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2577,14 +2577,23 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
 		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;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index bc7f522848e8423c61efe10037ef7eb79d982797..ba0a590910682168111842e8e9122a0c218b9161 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1097,11 +1097,13 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
 			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]);
@@ -1796,7 +1798,12 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
 							  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)
@@ -1851,6 +1858,12 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason
 							  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)
@@ -1905,6 +1918,11 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r
 							  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)
@@ -1959,6 +1977,12 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re
 							  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)
@@ -2013,6 +2037,12 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 							  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
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index f792f53ac58d76c08bde206a55fa0a20283eaa51..3d8150eed39c20f48d62e116d2affc081b5ec9f1 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -97,6 +97,13 @@ bool LLNotificationManager::onNotification(const LLSD& notify)
 {
 	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;
 
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index d58d6d536c0da5580cab4187b411af7989f0f6e2..d42056ef9d50736c3cd4c2f6582c2a011dc9c657 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -835,11 +835,11 @@ BOOL LLPanelEditWearable::isDirty() const
         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;
 }
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 18626e327307ba744c81029b0830233f590f11f2..04934b13f107569c6ce9f64e4cffef237998eb73 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -464,7 +464,9 @@ LLMultiPreview::LLMultiPreview()
 
 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();
@@ -477,8 +479,13 @@ void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)
 {
 	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);
 }
@@ -486,7 +493,9 @@ void LLMultiPreview::handleReshape(const LLRect& new_rect, bool 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();
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index d340b304ca802bfdabc61484f19023436c7fe8cb..d2280ea0890fae7fb0b7259565ff7d69a921862f 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -571,9 +571,13 @@ void LLScreenChannel::showToastsBottom()
 
 	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)
@@ -601,7 +605,7 @@ void LLScreenChannel::showToastsBottom()
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = floater->getRect().getHeight();
@@ -624,7 +628,7 @@ void LLScreenChannel::showToastsBottom()
 
 		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;
@@ -632,7 +636,8 @@ void LLScreenChannel::showToastsBottom()
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
@@ -655,10 +660,11 @@ void LLScreenChannel::showToastsBottom()
 	}
 
 	// 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)
@@ -714,9 +720,13 @@ void LLScreenChannel::showToastsTop()
 
 	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)
@@ -744,7 +754,7 @@ void LLScreenChannel::showToastsTop()
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = -floater->getRect().getHeight();
@@ -767,7 +777,7 @@ void LLScreenChannel::showToastsTop()
 
 		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;
@@ -775,7 +785,7 @@ void LLScreenChannel::showToastsTop()
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
@@ -799,10 +809,12 @@ void LLScreenChannel::showToastsTop()
 
 	// 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)
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 8eb8717de2d49edc3947a4e2f4cec190a68aa04f..32cf8cc1b30fd178ec7a015f538ab30ba4087da5 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1904,7 +1904,7 @@ void LLViewerFetchedTexture::updateVirtualSize()
 	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()) ;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 366b6004bee8420b316fd227b7512c532446d999..627238b0f52239540a3d7fca11b849c9139d0d7e 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -4421,7 +4421,9 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
 		}
 		// 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;
@@ -4565,7 +4567,20 @@ void LLVOAvatar::updateTextures()
 		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++)
 		{
@@ -8705,6 +8720,12 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 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);
 }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e99898a83c4a3dab4b62d0b7f7f5be785ac2c04a..5d1c3350785e80d5818283a00e69dc992aecc7fd 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1227,6 +1227,13 @@ BOOL LLVOVolume::calcLOD()
 	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();
 	}
@@ -1335,7 +1342,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
 
 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)
@@ -1436,7 +1444,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
 		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)
@@ -1737,6 +1748,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
 
 void LLVOVolume::updateFaceSize(S32 idx)
 {
+	if( mDrawable->getNumFaces() <= idx )
+	{
+		return;
+	}
+
 	LLFace* facep = mDrawable->getFace(idx);
 	if (facep)
 	{
@@ -2427,7 +2443,12 @@ void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index)
 	//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()) ;
@@ -3826,6 +3847,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 
 			LLVector4a* pos = dst_face.mPositions;
 
+			if( pos && weight && dst_face.mExtents )
 			{
 				LLFastTimer t(FTM_SKIN_RIGGED);
 
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index 2425b96678d1d0d6cdccbdd96f12e104a897c6e6..be3e3ff30e0cb6c4ba8c260d72c82f571ebfb05e 100644
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -105,10 +105,16 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
 		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;
 	}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 678898797f0ef7464e527c2a1298fed9c7457af6..91dd44131906119ec58dfc2301f689675691c921 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2011,6 +2011,7 @@ void LLPipeline::grabReferences(LLCullResult& result)
 void LLPipeline::clearReferences()
 {
 	sCull = NULL;
+	mGroupSaveQ1.clear();
 }
 
 void check_references(LLSpatialGroup* group, LLDrawable* drawable)
@@ -2619,6 +2620,7 @@ void LLPipeline::rebuildPriorityGroups()
 		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
 	}
 
+	mGroupSaveQ1 = mGroupQ1;
 	mGroupQ1.clear();
 	mGroupQ1Locked = false;
 
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index fd2a1e06cd47f094135fce9f89d1e56fa28f84bc..7a0ca86231f12ff6fe0528bc4f03036681b07d5f 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -668,6 +668,8 @@ class LLPipeline
 	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;
 
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index d480b63094745a1dea8d9593ce9a1f9529c9225d..bdcb068200768a17abbfc89c25d5d47fa80bb4de 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -271,6 +271,16 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
             }
             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"