diff options
author | Justin Clark-Casey (justincc) | 2015-01-29 17:55:08 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2015-01-29 17:55:08 +0000 |
commit | b4e955d1c107784ccf17a739cd83b2603f665d0c (patch) | |
tree | b3a60117c47a975625883ee714dd0b4fc317dda6 | |
parent | Correct typo in raw default script stop strategy (diff) | |
download | opensim-SC-b4e955d1c107784ccf17a739cd83b2603f665d0c.zip opensim-SC-b4e955d1c107784ccf17a739cd83b2603f665d0c.tar.gz opensim-SC-b4e955d1c107784ccf17a739cd83b2603f665d0c.tar.bz2 opensim-SC-b4e955d1c107784ccf17a739cd83b2603f665d0c.tar.xz |
Avoid a possible race condition by serializing plugin data outside the EventQueue lock in ScriptInstance.SaveState()
This takes the AsyncCommandHandler.staticLock.
However, AsyncCommandHandler.DoOneCmdHandlerPass() already holds staticLock and may attempt to take the EventQueue lock via ScriptInstance.PostEvent() in XEngine.CheckListeners()
This is a regression from faaf47a (Fri Jan 16 2015) but not simply reverting that commit since it will reintroduce a race between script removal, backup and event queue manipulating code.
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 5ff56a1..d28b151 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -1022,9 +1022,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
1022 | 1022 | ||
1023 | public void SaveState() | 1023 | public void SaveState() |
1024 | { | 1024 | { |
1025 | if (!Running) | ||
1026 | return; | ||
1027 | |||
1028 | // We cannot call this inside the EventQueue lock since it will currently take AsyncCommandManager.staticLock. | ||
1029 | // This may already be held by AsyncCommandManager.DoOneCmdHandlerPass() which in turn can take EventQueue | ||
1030 | // lock via ScriptInstance.PostEvent(). | ||
1031 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); | ||
1032 | |||
1025 | // We need to lock here to avoid any race with a thread that is removing this script. | 1033 | // We need to lock here to avoid any race with a thread that is removing this script. |
1026 | lock (EventQueue) | 1034 | lock (EventQueue) |
1027 | { | 1035 | { |
1036 | // Check again to avoid a race with a thread in Stop() | ||
1028 | if (!Running) | 1037 | if (!Running) |
1029 | return; | 1038 | return; |
1030 | 1039 | ||
@@ -1040,8 +1049,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
1040 | // "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", | 1049 | // "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", |
1041 | // ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); | 1050 | // ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); |
1042 | 1051 | ||
1043 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); | ||
1044 | |||
1045 | string xml = ScriptSerializer.Serialize(this); | 1052 | string xml = ScriptSerializer.Serialize(this); |
1046 | 1053 | ||
1047 | // Compare hash of the state we just just created with the state last written to disk | 1054 | // Compare hash of the state we just just created with the state last written to disk |