diff options
author | Justin Clark-Casey (justincc) | 2015-03-12 00:07:01 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2015-03-12 00:07:01 +0000 |
commit | 7410924de0b3adf3f93e0e661d99f4ab033680b9 (patch) | |
tree | 40a20d2b1e01df2a99236a9402a317a8e8bc3801 | |
parent | A workaround for the state change problem described best here http://opensimu... (diff) | |
download | opensim-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.cs | 41 |
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 | } |