diff options
author | Justin Clark-Casey (justincc) | 2015-01-16 23:55:00 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2015-01-16 23:55:11 +0000 |
commit | faaf47a86f34f24dec0d7d51eda638d0df3db305 (patch) | |
tree | 999a9351ae53e4ecc0b465e8e1bea744cb335837 /OpenSim/Region/ScriptEngine/Shared/Instance | |
parent | For scripts in attachments, don't save .state files apart from the initial on... (diff) | |
download | opensim-SC-faaf47a86f34f24dec0d7d51eda638d0df3db305.zip opensim-SC-faaf47a86f34f24dec0d7d51eda638d0df3db305.tar.gz opensim-SC-faaf47a86f34f24dec0d7d51eda638d0df3db305.tar.bz2 opensim-SC-faaf47a86f34f24dec0d7d51eda638d0df3db305.tar.xz |
Prevent a race condition between the script engine backup thread and script removal by locking on the script's EventQueue and only proceeding if it's flagged as still running.
Relates to http://opensimulator.org/mantis/view.php?id=7407
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 9498aa8..e202a24 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -564,7 +564,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
564 | } | 564 | } |
565 | } | 565 | } |
566 | 566 | ||
567 | public bool Stop(int timeout) | 567 | public bool Stop(int timeout, bool clearEventQueue = false) |
568 | { | 568 | { |
569 | if (DebugLevel >= 1) | 569 | if (DebugLevel >= 1) |
570 | m_log.DebugFormat( | 570 | m_log.DebugFormat( |
@@ -575,6 +575,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
575 | 575 | ||
576 | lock (EventQueue) | 576 | lock (EventQueue) |
577 | { | 577 | { |
578 | if (clearEventQueue) | ||
579 | ClearQueue(); | ||
580 | |||
578 | if (!Running) | 581 | if (!Running) |
579 | return true; | 582 | return true; |
580 | 583 | ||
@@ -1065,45 +1068,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
1065 | 1068 | ||
1066 | public void SaveState() | 1069 | public void SaveState() |
1067 | { | 1070 | { |
1068 | // If we're currently in an event, just tell it to save upon return | 1071 | // We need to lock here to avoid any race with a thread that is removing this script. |
1069 | // | 1072 | lock (EventQueue) |
1070 | if (m_InEvent) | ||
1071 | { | 1073 | { |
1072 | m_SaveState = true; | 1074 | if (!Running) |
1073 | return; | 1075 | return; |
1074 | } | ||
1075 | 1076 | ||
1076 | // m_log.DebugFormat( | 1077 | // If we're currently in an event, just tell it to save upon return |
1077 | // "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", | 1078 | // |
1078 | // ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); | 1079 | if (m_InEvent) |
1080 | { | ||
1081 | m_SaveState = true; | ||
1082 | return; | ||
1083 | } | ||
1079 | 1084 | ||
1080 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); | 1085 | // m_log.DebugFormat( |
1086 | // "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", | ||
1087 | // ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); | ||
1081 | 1088 | ||
1082 | string xml = ScriptSerializer.Serialize(this); | 1089 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); |
1083 | 1090 | ||
1084 | // Compare hash of the state we just just created with the state last written to disk | 1091 | string xml = ScriptSerializer.Serialize(this); |
1085 | // If the state is different, update the disk file. | ||
1086 | UUID hash = UUID.Parse(Utils.MD5String(xml)); | ||
1087 | 1092 | ||
1088 | if (hash != m_CurrentStateHash) | 1093 | // Compare hash of the state we just just created with the state last written to disk |
1089 | { | 1094 | // If the state is different, update the disk file. |
1090 | try | 1095 | UUID hash = UUID.Parse(Utils.MD5String(xml)); |
1096 | |||
1097 | if (hash != m_CurrentStateHash) | ||
1091 | { | 1098 | { |
1092 | using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state"))) | 1099 | try |
1100 | { | ||
1101 | using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state"))) | ||
1102 | { | ||
1103 | Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); | ||
1104 | fs.Write(buf, 0, buf.Length); | ||
1105 | } | ||
1106 | } | ||
1107 | catch(Exception) | ||
1093 | { | 1108 | { |
1094 | Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); | 1109 | // m_log.Error("Unable to save xml\n"+e.ToString()); |
1095 | fs.Write(buf, 0, buf.Length); | ||
1096 | } | 1110 | } |
1111 | //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) | ||
1112 | //{ | ||
1113 | // throw new Exception("Completed persistence save, but no file was created"); | ||
1114 | //} | ||
1115 | m_CurrentStateHash = hash; | ||
1097 | } | 1116 | } |
1098 | catch(Exception) | ||
1099 | { | ||
1100 | // m_log.Error("Unable to save xml\n"+e.ToString()); | ||
1101 | } | ||
1102 | //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) | ||
1103 | //{ | ||
1104 | // throw new Exception("Completed persistence save, but no file was created"); | ||
1105 | //} | ||
1106 | m_CurrentStateHash = hash; | ||
1107 | } | 1117 | } |
1108 | } | 1118 | } |
1109 | 1119 | ||