From faaf47a86f34f24dec0d7d51eda638d0df3db305 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 16 Jan 2015 23:55:00 +0000 Subject: 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 --- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 70 ++++++++++++---------- 1 file changed, 40 insertions(+), 30 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 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 } } - public bool Stop(int timeout) + public bool Stop(int timeout, bool clearEventQueue = false) { if (DebugLevel >= 1) m_log.DebugFormat( @@ -575,6 +575,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance lock (EventQueue) { + if (clearEventQueue) + ClearQueue(); + if (!Running) return true; @@ -1065,45 +1068,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public void SaveState() { - // If we're currently in an event, just tell it to save upon return - // - if (m_InEvent) + // We need to lock here to avoid any race with a thread that is removing this script. + lock (EventQueue) { - m_SaveState = true; - return; - } + if (!Running) + return; -// m_log.DebugFormat( -// "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", -// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); + // If we're currently in an event, just tell it to save upon return + // + if (m_InEvent) + { + m_SaveState = true; + return; + } - PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); + // m_log.DebugFormat( + // "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}", + // ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); - string xml = ScriptSerializer.Serialize(this); + PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); - // Compare hash of the state we just just created with the state last written to disk - // If the state is different, update the disk file. - UUID hash = UUID.Parse(Utils.MD5String(xml)); + string xml = ScriptSerializer.Serialize(this); - if (hash != m_CurrentStateHash) - { - try + // Compare hash of the state we just just created with the state last written to disk + // If the state is different, update the disk file. + UUID hash = UUID.Parse(Utils.MD5String(xml)); + + if (hash != m_CurrentStateHash) { - using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state"))) + try + { + using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state"))) + { + Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); + fs.Write(buf, 0, buf.Length); + } + } + catch(Exception) { - Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); - fs.Write(buf, 0, buf.Length); + // m_log.Error("Unable to save xml\n"+e.ToString()); } + //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) + //{ + // throw new Exception("Completed persistence save, but no file was created"); + //} + m_CurrentStateHash = hash; } - catch(Exception) - { - // m_log.Error("Unable to save xml\n"+e.ToString()); - } - //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) - //{ - // throw new Exception("Completed persistence save, but no file was created"); - //} - m_CurrentStateHash = hash; } } -- cgit v1.1