From 2c30ccf34d518ccedd0b3ffdeb2ba1da8d140a1d Mon Sep 17 00:00:00 2001
From: Tofu Linden <tofu.linden@lindenlab.com>
Date: Thu, 4 Feb 2010 11:24:14 +0000
Subject: [PATCH] EXT-4754 Crash in LLEventTimer::updateClass

---
 indra/llcommon/lltimer.cpp      |  2 +-
 indra/newview/llcallfloater.cpp |  3 ++-
 indra/newview/llspeakers.cpp    | 17 ++++++++++-------
 indra/newview/llspeakers.h      |  4 ++--
 4 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 63634117b5f..21e165ebc99 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -578,7 +578,7 @@ LLEventTimer::LLEventTimer(const LLDate& time)
 
 LLEventTimer::~LLEventTimer()
 {
-	llassert(!mBusy); // this LLEventTimer was destroyed from its own tick() function - bad.
+	llassert(!mBusy); // this LLEventTimer was destroyed from within its own tick() function - bad.  if you want tick() to cause destruction of its own timer, make it return true.
 }
 
 //static
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 8cb240c7c26..bd4fae6ab65 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -678,7 +678,8 @@ void LLCallFloater::resetVoiceRemoveTimers()
 
 void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
 {
-	mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
+	bool delete_it = true;
+	mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id, delete_it);
 }
 
 bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 6f9a1ccdbe0..786fa24e659 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -205,7 +205,7 @@ void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
 	}
 }
 
-void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
+void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id, bool delete_it)
 {
 	if (mActionTimersMap.size() == 0) return;
 
@@ -213,7 +213,10 @@ void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
 
 	if (it_speaker != mActionTimersMap.end())
 	{
-		delete it_speaker->second;
+		if (delete_it)
+		{
+			delete it_speaker->second;
+		}
 		mActionTimersMap.erase(it_speaker);
 	}
 }
@@ -230,16 +233,15 @@ void LLSpeakersDelayActionsStorage::removeAllTimers()
 
 bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
 {
-	unsetActionTimer(speaker_id);
+	bool delete_it = false; // we're *in* this timer, return true to delete it, don't manually delete it
+	unsetActionTimer(speaker_id, delete_it);
 
 	if (mActionCallback)
 	{
 		mActionCallback(speaker_id);
 	}
 
-	// do not return true to avoid deleting of an timer twice:
-	// in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
-	return false;
+	return true;
 }
 
 
@@ -291,7 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
 		}
 	}
 
-	mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
+	bool delete_it = true;
+	mSpeakerDelayRemover->unsetActionTimer(speakerp->mID, delete_it);
 
 	return speakerp;
 }
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 63237204c86..ddc3632f075 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -176,11 +176,11 @@ class LLSpeakersDelayActionsStorage
 	void setActionTimer(const LLUUID& speaker_id);
 
 	/**
-	 * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
+	 * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and optionally deletes it.
 	 *
 	 * @see onTimerActionCallback()
 	 */
-	void unsetActionTimer(const LLUUID& speaker_id);
+	void unsetActionTimer(const LLUUID& speaker_id, bool delete_it);
 
 	void removeAllTimers();
 private:
-- 
GitLab