From 7410924de0b3adf3f93e0e661d99f4ab033680b9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 12 Mar 2015 00:07:01 +0000 Subject: Lock around EventQueue manipulation in ScriptInstance.SetState() as queues are not thread-safe structures. This should also make it less likely that an event will be erroneously posted during a state change by precluding a race condition with a thread calling ScriptInstance.PostEvent() --- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared/Instance') diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 7c7b831..fe711d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -618,26 +618,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { if (state == State) return; - - // Remove all queued events, remembering the last timer event + EventParams lastTimerEv = null; - while (EventQueue.Count > 0) + + lock (EventQueue) { - EventParams tempv = (EventParams)EventQueue.Dequeue(); - if (tempv.EventName == "timer") lastTimerEv = tempv; + // Remove all queued events, remembering the last timer event + while (EventQueue.Count > 0) + { + EventParams tempv = (EventParams)EventQueue.Dequeue(); + if (tempv.EventName == "timer") lastTimerEv = tempv; + } + + // Post events + PostEvent(new EventParams("state_exit", new Object[0], + new DetectParams[0])); + PostEvent(new EventParams("state", new Object[] { state }, + new DetectParams[0])); + PostEvent(new EventParams("state_entry", new Object[0], + new DetectParams[0])); + + // Requeue the timer event after the state changing events + if (lastTimerEv != null) EventQueue.Enqueue(lastTimerEv); + + // This will stop events from being queued and processed + // until the new state is started + m_StateChangeInProgress = true; } - // Post events - PostEvent(new EventParams("state_exit", new Object[0], - new DetectParams[0])); - PostEvent(new EventParams("state", new Object[] { state }, - new DetectParams[0])); - PostEvent(new EventParams("state_entry", new Object[0], - new DetectParams[0])); - // Requeue the timer event after the state changing events - if (lastTimerEv != null) EventQueue.Enqueue(lastTimerEv); - // This will stop events from being queued and processed - // until the new state is started - m_StateChangeInProgress = true; throw new EventAbortException(); } -- cgit v1.1