aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2015-03-12 00:07:01 +0000
committerJustin Clark-Casey (justincc)2015-03-12 00:07:01 +0000
commit7410924de0b3adf3f93e0e661d99f4ab033680b9 (patch)
tree40a20d2b1e01df2a99236a9402a317a8e8bc3801
parentA workaround for the state change problem described best here http://opensimu... (diff)
downloadopensim-SC-7410924de0b3adf3f93e0e661d99f4ab033680b9.zip
opensim-SC-7410924de0b3adf3f93e0e661d99f4ab033680b9.tar.gz
opensim-SC-7410924de0b3adf3f93e0e661d99f4ab033680b9.tar.bz2
opensim-SC-7410924de0b3adf3f93e0e661d99f4ab033680b9.tar.xz
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()
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs41
1 files changed, 24 insertions, 17 deletions
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
618 { 618 {
619 if (state == State) 619 if (state == State)
620 return; 620 return;
621 621
622 // Remove all queued events, remembering the last timer event
623 EventParams lastTimerEv = null; 622 EventParams lastTimerEv = null;
624 while (EventQueue.Count > 0) 623
624 lock (EventQueue)
625 { 625 {
626 EventParams tempv = (EventParams)EventQueue.Dequeue(); 626 // Remove all queued events, remembering the last timer event
627 if (tempv.EventName == "timer") lastTimerEv = tempv; 627 while (EventQueue.Count > 0)
628 {
629 EventParams tempv = (EventParams)EventQueue.Dequeue();
630 if (tempv.EventName == "timer") lastTimerEv = tempv;
631 }
632
633 // Post events
634 PostEvent(new EventParams("state_exit", new Object[0],
635 new DetectParams[0]));
636 PostEvent(new EventParams("state", new Object[] { state },
637 new DetectParams[0]));
638 PostEvent(new EventParams("state_entry", new Object[0],
639 new DetectParams[0]));
640
641 // Requeue the timer event after the state changing events
642 if (lastTimerEv != null) EventQueue.Enqueue(lastTimerEv);
643
644 // This will stop events from being queued and processed
645 // until the new state is started
646 m_StateChangeInProgress = true;
628 } 647 }
629 // Post events
630 PostEvent(new EventParams("state_exit", new Object[0],
631 new DetectParams[0]));
632 PostEvent(new EventParams("state", new Object[] { state },
633 new DetectParams[0]));
634 PostEvent(new EventParams("state_entry", new Object[0],
635 new DetectParams[0]));
636 // Requeue the timer event after the state changing events
637 if (lastTimerEv != null) EventQueue.Enqueue(lastTimerEv);
638 // This will stop events from being queued and processed
639 // until the new state is started
640 m_StateChangeInProgress = true;
641 648
642 throw new EventAbortException(); 649 throw new EventAbortException();
643 } 650 }