From b8949024bc55c62b9268b35d4f2a568760b9d7d3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 16 Jan 2013 01:45:09 +0000 Subject: [PATCH 1/8] Revert "Implement co-operative script termination if termination comes during a script wait event (llSleep(), etc.)" Doing this as a favour to Melanie. This will be back with passing the wait handles directly to the api. This reverts commit 1b5c41c14ad11325be249ea1cce3c65d4d6a89be. --- .../Framework/Scenes/Scene.Inventory.cs | 26 +-- .../Interfaces/IScriptInstance.cs | 13 -- .../Shared/Api/Implementation/LSL_Api.cs | 31 +--- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 18 -- .../Shared/Instance/ScriptInstance.cs | 52 +----- .../Instance/Tests/CoopTerminationTests.cs | 157 ------------------ .../Region/ScriptEngine/XEngine/XEngine.cs | 5 - prebuild.xml | 5 +- 8 files changed, 14 insertions(+), 293 deletions(-) delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 92bf85aabd..5c8b097216 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1737,21 +1737,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// The part where the script was rezzed if successful. False otherwise. public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase) - { - return RezNewScript( - agentID, - itemBase, - "default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"); - } - - /// - /// Rez a new script from nothing with given script text. - /// - /// - /// Template item. - /// - /// The part where the script was rezzed if successful. False otherwise. - public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase, string scriptText) { // The part ID is the folder ID! SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); @@ -1772,14 +1757,9 @@ namespace OpenSim.Region.Framework.Scenes return null; } - AssetBase asset - = CreateAsset( - itemBase.Name, - itemBase.Description, - (sbyte)itemBase.AssetType, - Encoding.ASCII.GetBytes(scriptText), - agentID); - + AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, + Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), + agentID); AssetService.Store(asset); TaskInventoryItem taskItem = new TaskInventoryItem(); diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index 38fff521a8..9de2d725f2 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Threading; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -181,18 +180,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces void Suspend(); void Resume(); - /// - /// If true then scripts should look to terminate their threads in co-operation with the script engine rather - /// than through Thread.Abort() - /// - bool CoopTermination { get; } - - /// - /// Used for script sleeps when we are using co-operative script termination. - /// - /// null if CoopTermination is not active - EventWaitHandle CoopSleepHandle { get; } - /// /// Process the next event queued for this script instance. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b992efa814..44072c6c36 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -83,12 +83,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Instance of this script. - /// - protected IScriptInstance m_scriptInstance; - protected IScriptEngine m_ScriptEngine; protected SceneObjectPart m_host; @@ -118,12 +112,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void Initialize(IScriptInstance scriptInstance) { - m_scriptInstance = scriptInstance; - m_ScriptEngine = m_scriptInstance.Engine; - m_host = m_scriptInstance.Part; - m_item = m_scriptInstance.ScriptTask; + m_ScriptEngine = scriptInstance.Engine; + m_host = scriptInstance.Part; + m_item = scriptInstance.ScriptTask; - LoadConfig(); + LoadLimits(); // read script limits from config. m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); @@ -136,7 +129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// Load configuration items that affect script, object and run-time behavior. */ /// - private void LoadConfig() + private void LoadLimits() { m_ScriptDelayFactor = m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); @@ -182,16 +175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api delay = (int)((float)delay * m_ScriptDelayFactor); if (delay == 0) return; - - Sleep(delay); - } - - protected virtual void Sleep(int delay) - { - if (!m_scriptInstance.CoopTermination) - System.Threading.Thread.Sleep(delay); - else if (m_scriptInstance.CoopSleepHandle.WaitOne(delay)) - throw new ScriptCoopStopException(); + System.Threading.Thread.Sleep(delay); } public Scene World @@ -2930,8 +2914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // m_log.Info("llSleep snoozing " + sec + "s."); m_host.AddScriptLPS(1); - - Sleep((int)(sec * 1000)); + Thread.Sleep((int)(sec * 1000)); } public LSL_Float llGetMass() diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index e02d35ed6d..5a58f734ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -81,24 +81,6 @@ namespace OpenSim.Region.ScriptEngine.Shared } } - /// - /// Used to signal when the script is stopping in co-operation with the script engine - /// (instead of through Thread.Abort()). - /// - [Serializable] - public class ScriptCoopStopException : Exception - { - public ScriptCoopStopException() - { - } - - protected ScriptCoopStopException( - SerializationInfo info, - StreamingContext context) - { - } - } - public class DetectParams { public const int AGENT = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 00048a1dfc..a2ff51b59f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -200,10 +200,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; - public bool CoopTermination { get; private set; } - - public EventWaitHandle CoopSleepHandle { get; private set; } - public void ClearQueue() { m_TimerQueued = false; @@ -237,12 +233,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_postOnRez = postOnRez; m_AttachedAvatar = Part.ParentGroup.AttachedAvatar; m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID; - - if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op") - { - CoopTermination = true; - CoopSleepHandle = new AutoResetEvent(false); - } } /// @@ -542,34 +532,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } // Wait for the current event to complete. - if (!m_InSelfDelete) + if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) { - if (!CoopTermination) - { - // If we're not co-operative terminating then try and wait for the event to complete before stopping - if (workItem.Wait(new TimeSpan((long)timeout * 100000))) - return true; - } - else - { - m_log.DebugFormat( - "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}", - ScriptName, ItemID, PrimName, ObjectID); - - // This will terminate the event on next handle check by the script. - CoopSleepHandle.Set(); - - // For now, we will wait forever since the event should always cleanly terminate once LSL loop - // checking is implemented. May want to allow a shorter timeout option later. - if (workItem.Wait(TimeSpan.MaxValue)) - { - m_log.DebugFormat( - "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}", - ScriptName, ItemID, PrimName, ObjectID); - - return true; - } - } + return true; } lock (EventQueue) @@ -582,7 +547,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then // forcibly abort the work item (this aborts the underlying thread). - // Co-operative termination should never reach this point. if (!m_InSelfDelete) { m_log.DebugFormat( @@ -822,11 +786,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_InEvent = false; m_CurrentEvent = String.Empty; - if ((!(e is TargetInvocationException) - || (!(e.InnerException is SelfDeleteException) - && !(e.InnerException is ScriptDeleteException) - && !(e.InnerException is ScriptCoopStopException))) - && !(e is ThreadAbortException)) + if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) { try { @@ -874,12 +834,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_InSelfDelete = true; Part.Inventory.RemoveInventoryItem(ItemID); } - else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException)) - { - m_log.DebugFormat( - "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.", - PrimName, ScriptName, data.EventName, State); - } } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs deleted file mode 100644 index f3a6cc9503..0000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Threading; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.WorldComm; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.ScriptEngine.XEngine; -using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Mock; - -namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests -{ - /// - /// Test that co-operative script thread termination is working correctly. - /// - [TestFixture] - public class CoopTerminationTests : OpenSimTestCase - { - private TestScene m_scene; - private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine; - - private AutoResetEvent m_chatEvent = new AutoResetEvent(false); - private AutoResetEvent m_stoppedEvent = new AutoResetEvent(false); - - private OSChatMessage m_osChatMessageReceived; - - [TestFixtureSetUp] - public void Init() - { - //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin"); -// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); - m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine(); - - IniConfigSource configSource = new IniConfigSource(); - - IConfig startupConfig = configSource.AddConfig("Startup"); - startupConfig.Set("DefaultScriptEngine", "XEngine"); - - IConfig xEngineConfig = configSource.AddConfig("XEngine"); - xEngineConfig.Set("Enabled", "true"); - xEngineConfig.Set("StartDelay", "0"); - - // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call - // to AssemblyResolver.OnAssemblyResolve fails. - xEngineConfig.Set("AppDomainLoading", "false"); - - xEngineConfig.Set("ScriptStopStrategy", "co-op"); - - m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); - SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); - m_scene.StartScripts(); - } - - /// - /// Test co-operative termination on derez of an object containing a script with a long-running event. - /// - /// - /// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts - /// within the build itself. - /// - [Test] - public void TestStopOnLongSleep() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x100); -// UUID itemId = TestHelpers.ParseTail(0x3); - string itemName = "TestStopOnObjectDerezLongSleep() Item"; - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100); - m_scene.AddNewSceneObject(so, true); - - InventoryItemBase itemTemplate = new InventoryItemBase(); -// itemTemplate.ID = itemId; - itemTemplate.Name = itemName; - itemTemplate.Folder = so.UUID; - itemTemplate.InvType = (int)InventoryType.LSL; - - m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - - SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, -@"default -{ - state_entry() - { - llSay(0, ""Thin Lizzy""); - llSleep(60); - } -}"); - - TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - - // Wait for the script to start the event before we try stopping it. - m_chatEvent.WaitOne(60000); - - Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message); - - // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script - // executes llSay() but has not started the sleep before we try to stop it. - Thread.Sleep(1000); - - // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually - // stopped. This kind of multi-threading is far from ideal in a regression test. - new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start(); - - if (!m_stoppedEvent.WaitOne(30000)) - Assert.Fail("Script did not co-operatively stop."); - - bool running; - TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - Assert.That( - SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); - Assert.That(running, Is.False); - } - - private void OnChatFromWorld(object sender, OSChatMessage oscm) - { -// Console.WriteLine("Got chat [{0}]", oscm.Message); - - m_osChatMessageReceived = oscm; - m_chatEvent.Set(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a17a0188bb..186ae041bf 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1716,14 +1716,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) - { instance.Stop(m_WaitForEventCompletionOnScriptStop); - } else - { -// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); m_runFlags.AddOrUpdate(itemID, false, 240); - } } public DetectParams GetDetectParams(UUID itemID, int idx) diff --git a/prebuild.xml b/prebuild.xml index abf8f364d7..c6bef5cbbe 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2417,9 +2417,7 @@ - - - + @@ -3311,7 +3309,6 @@ - From 0963ece25bdef16852f5fd8ae4515a2f05d8b6e4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 16 Jan 2013 02:07:43 +0000 Subject: [PATCH 2/8] Implement co-operative script termination if termination comes during a script wait event (llSleep(), etc.) This makes use of EventWaitHandles since various web references indicate that Thread.Interrupt() can also cause runtime instability. If co-op termination is enabled, then termination sets the wait handle instead of waiting for a timeout before possibly aborting the thread. This allows the script to cleanly terminate if it's in a llSleep/LL function delay or the next time it enters such a wait without any timeout period. Co-op termination is not yet testable since checking for termination request within loops that never trigger a wait is not yet implemented. This commit, unlike 1b5c41c, passes the wait handle as an extra parameter through IScript.Initialize() instead of passing IScriptInstance itself. --- .../Framework/Scenes/Scene.Inventory.cs | 26 ++- .../ScriptEngine/Interfaces/IScriptApi.cs | 9 +- .../Interfaces/IScriptInstance.cs | 1 + .../Shared/Api/Implementation/LSL_Api.cs | 35 +++- .../Shared/Api/Implementation/LS_Api.cs | 8 +- .../Shared/Api/Implementation/MOD_Api.cs | 10 +- .../Shared/Api/Implementation/OSSL_Api.cs | 9 +- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 18 ++ .../Shared/Instance/ScriptInstance.cs | 54 +++++- .../Instance/Tests/CoopTerminationTests.cs | 157 ++++++++++++++++++ .../Shared/Tests/LSL_ApiInventoryTests.cs | 6 +- .../Shared/Tests/LSL_ApiLinkingTests.cs | 4 +- .../Shared/Tests/LSL_ApiListTests.cs | 2 +- .../ScriptEngine/Shared/Tests/LSL_ApiTest.cs | 2 +- .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 4 +- .../Shared/Tests/OSSL_ApiAttachmentTests.cs | 15 +- .../Shared/Tests/OSSL_ApiNpcTests.cs | 16 +- .../Region/ScriptEngine/XEngine/XEngine.cs | 5 + prebuild.xml | 5 +- 19 files changed, 331 insertions(+), 55 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5c8b097216..92bf85aabd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1737,6 +1737,21 @@ namespace OpenSim.Region.Framework.Scenes /// /// The part where the script was rezzed if successful. False otherwise. public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase) + { + return RezNewScript( + agentID, + itemBase, + "default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"); + } + + /// + /// Rez a new script from nothing with given script text. + /// + /// + /// Template item. + /// + /// The part where the script was rezzed if successful. False otherwise. + public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase, string scriptText) { // The part ID is the folder ID! SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); @@ -1757,9 +1772,14 @@ namespace OpenSim.Region.Framework.Scenes return null; } - AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, - Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), - agentID); + AssetBase asset + = CreateAsset( + itemBase.Name, + itemBase.Description, + (sbyte)itemBase.AssetType, + Encoding.ASCII.GetBytes(scriptText), + agentID); + AssetService.Store(asset); TaskInventoryItem taskItem = new TaskInventoryItem(); diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs index e95cbd7213..d2323f56d1 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs @@ -26,6 +26,7 @@ */ using System; +using System.Threading; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; @@ -40,7 +41,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces /// /// /// Each API has an identifier, which is used to load the proper runtime assembly at load time. - /// /param> - void Initialize(IScriptInstance scriptInstance); + /// /param> + /// /param> + /// /param> + /// /param> + void Initialize( + IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle); } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index 9de2d725f2..f68612c15e 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Threading; using OpenMetaverse; using log4net; using OpenSim.Framework; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 44072c6c36..d47fd6b5ac 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -83,9 +83,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected IScriptEngine m_ScriptEngine; protected SceneObjectPart m_host; + /// + /// Used for script sleeps when we are using co-operative script termination. + /// + /// null if co-operative script termination is not active + EventWaitHandle m_coopSleepHandle; + /// /// The item that hosts this script /// @@ -110,13 +117,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. protected ISoundModule m_SoundModule = null; - public void Initialize(IScriptInstance scriptInstance) + public void Initialize( + IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) { - m_ScriptEngine = scriptInstance.Engine; - m_host = scriptInstance.Part; - m_item = scriptInstance.ScriptTask; + m_ScriptEngine = scriptEngine; + m_host = host; + m_item = item; + m_coopSleepHandle = coopSleepHandle; - LoadLimits(); // read script limits from config. + LoadConfig(); m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); @@ -129,7 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// Load configuration items that affect script, object and run-time behavior. */ /// - private void LoadLimits() + private void LoadConfig() { m_ScriptDelayFactor = m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); @@ -175,7 +184,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api delay = (int)((float)delay * m_ScriptDelayFactor); if (delay == 0) return; - System.Threading.Thread.Sleep(delay); + + Sleep(delay); + } + + protected virtual void Sleep(int delay) + { + if (m_coopSleepHandle == null) + System.Threading.Thread.Sleep(delay); + else if (m_coopSleepHandle.WaitOne(delay)) + throw new ScriptCoopStopException(); } public Scene World @@ -2914,7 +2932,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // m_log.Info("llSleep snoozing " + sec + "s."); m_host.AddScriptLPS(1); - Thread.Sleep((int)(sec * 1000)); + + Sleep((int)(sec * 1000)); } public LSL_Float llGetMass() diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 071c60ef2b..a08ccc889e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -30,6 +30,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Runtime.Remoting.Lifetime; +using System.Threading; using OpenMetaverse; using Nini.Config; using OpenSim; @@ -61,10 +62,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal bool m_LSFunctionsEnabled = false; internal IScriptModuleComms m_comms = null; - public void Initialize(IScriptInstance scriptInstance) + public void Initialize( + IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) { - m_ScriptEngine = scriptInstance.Engine; - m_host = scriptInstance.Part; + m_ScriptEngine = scriptEngine; + m_host = host; if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) m_LSFunctionsEnabled = true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index cbc69aaa37..981499ea92 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -30,6 +30,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Runtime.Remoting.Lifetime; +using System.Threading; using OpenMetaverse; using Nini.Config; using OpenSim; @@ -61,11 +62,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal bool m_MODFunctionsEnabled = false; internal IScriptModuleComms m_comms = null; - public void Initialize(IScriptInstance scriptInstance) + public void Initialize( + IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) { - m_ScriptEngine = scriptInstance.Engine; - m_host = scriptInstance.Part; - m_item = scriptInstance.ScriptTask; + m_ScriptEngine = scriptEngine; + m_host = host; + m_item = item; if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false)) m_MODFunctionsEnabled = true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 33ae5f0649..25635ff767 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -142,11 +142,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected IUrlModule m_UrlModule = null; - public void Initialize(IScriptInstance scriptInstance) + public void Initialize( + IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) { - m_ScriptEngine = scriptInstance.Engine; - m_host = scriptInstance.Part; - m_item = scriptInstance.ScriptTask; + m_ScriptEngine = scriptEngine; + m_host = host; + m_item = item; m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 5a58f734ff..e02d35ed6d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -81,6 +81,24 @@ namespace OpenSim.Region.ScriptEngine.Shared } } + /// + /// Used to signal when the script is stopping in co-operation with the script engine + /// (instead of through Thread.Abort()). + /// + [Serializable] + public class ScriptCoopStopException : Exception + { + public ScriptCoopStopException() + { + } + + protected ScriptCoopStopException( + SerializationInfo info, + StreamingContext context) + { + } + } + public class DetectParams { public const int AGENT = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index a2ff51b59f..75aea2b0b1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -200,6 +200,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; + private bool m_coopTermination; + + private EventWaitHandle m_coopSleepHandle; + public void ClearQueue() { m_TimerQueued = false; @@ -233,6 +237,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_postOnRez = postOnRez; m_AttachedAvatar = Part.ParentGroup.AttachedAvatar; m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID; + + if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op") + { + m_coopTermination = true; + m_coopSleepHandle = new AutoResetEvent(false); + } } /// @@ -251,7 +261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance foreach (string api in am.GetApis()) { m_Apis[api] = am.CreateApi(api); - m_Apis[api].Initialize(this); + m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle); } try @@ -532,9 +542,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } // Wait for the current event to complete. - if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) + if (!m_InSelfDelete) { - return true; + if (!m_coopTermination) + { + // If we're not co-operative terminating then try and wait for the event to complete before stopping + if (workItem.Wait(new TimeSpan((long)timeout * 100000))) + return true; + } + else + { + m_log.DebugFormat( + "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}", + ScriptName, ItemID, PrimName, ObjectID); + + // This will terminate the event on next handle check by the script. + m_coopSleepHandle.Set(); + + // For now, we will wait forever since the event should always cleanly terminate once LSL loop + // checking is implemented. May want to allow a shorter timeout option later. + if (workItem.Wait(TimeSpan.MaxValue)) + { + m_log.DebugFormat( + "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}", + ScriptName, ItemID, PrimName, ObjectID); + + return true; + } + } } lock (EventQueue) @@ -547,6 +582,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then // forcibly abort the work item (this aborts the underlying thread). + // Co-operative termination should never reach this point. if (!m_InSelfDelete) { m_log.DebugFormat( @@ -786,7 +822,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_InEvent = false; m_CurrentEvent = String.Empty; - if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) + if ((!(e is TargetInvocationException) + || (!(e.InnerException is SelfDeleteException) + && !(e.InnerException is ScriptDeleteException) + && !(e.InnerException is ScriptCoopStopException))) + && !(e is ThreadAbortException)) { try { @@ -834,6 +874,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_InSelfDelete = true; Part.Inventory.RemoveInventoryItem(ItemID); } + else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException)) + { + m_log.DebugFormat( + "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.", + PrimName, ScriptName, data.EventName, State); + } } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs new file mode 100644 index 0000000000..8c3e9e0b47 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -0,0 +1,157 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Threading; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Scripting.WorldComm; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ScriptEngine.XEngine; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests +{ + /// + /// Test that co-operative script thread termination is working correctly. + /// + [TestFixture] + public class CoopTerminationTests : OpenSimTestCase + { + private TestScene m_scene; + private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine; + + private AutoResetEvent m_chatEvent = new AutoResetEvent(false); + private AutoResetEvent m_stoppedEvent = new AutoResetEvent(false); + + private OSChatMessage m_osChatMessageReceived; + + [TestFixtureSetUp] + public void Init() + { + //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin"); +// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); + m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine(); + + IniConfigSource configSource = new IniConfigSource(); + + IConfig startupConfig = configSource.AddConfig("Startup"); + startupConfig.Set("DefaultScriptEngine", "XEngine"); + + IConfig xEngineConfig = configSource.AddConfig("XEngine"); + xEngineConfig.Set("Enabled", "true"); + xEngineConfig.Set("StartDelay", "0"); + + // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call + // to AssemblyResolver.OnAssemblyResolve fails. + xEngineConfig.Set("AppDomainLoading", "false"); + + xEngineConfig.Set("ScriptStopStrategy", "co-op"); + + m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); + SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); + m_scene.StartScripts(); + } + + /// + /// Test co-operative termination on derez of an object containing a script with a long-running event. + /// + /// + /// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts + /// within the build itself. + /// + [Test] + public void TestStopOnLongSleep() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); +// UUID objectId = TestHelpers.ParseTail(0x100); +// UUID itemId = TestHelpers.ParseTail(0x3); + string itemName = "TestStopOnObjectDerezLongSleep() Item"; + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100); + m_scene.AddNewSceneObject(so, true); + + InventoryItemBase itemTemplate = new InventoryItemBase(); +// itemTemplate.ID = itemId; + itemTemplate.Name = itemName; + itemTemplate.Folder = so.UUID; + itemTemplate.InvType = (int)InventoryType.LSL; + + m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; + + SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, +@"default +{ + state_entry() + { + llSay(0, ""Thin Lizzy""); + llSleep(60); + } +}"); + + TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); + + // Wait for the script to start the event before we try stopping it. + m_chatEvent.WaitOne(60000); + + Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message); + + // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script + // executes llSay() but has not started the sleep before we try to stop it. + Thread.Sleep(1000); + + // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually + // stopped. This kind of multi-threading is far from ideal in a regression test. + new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start(); + + if (!m_stoppedEvent.WaitOne(30000)) + Assert.Fail("Script did not co-operatively stop."); + + bool running; + TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); + Assert.That( + SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); + Assert.That(running, Is.False); + } + + private void OnChatFromWorld(object sender, OSChatMessage oscm) + { +// Console.WriteLine("Got chat [{0}]", oscm.Message); + + m_osChatMessageReceived = oscm; + m_chatEvent.Set(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs index 36c75829a1..6dd6c170b7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId); LSL_Api api = new LSL_Api(); - api.Initialize(new ScriptInstance(m_engine, so1.RootPart, null, 0, false, int.MaxValue)); + api.Initialize(m_engine, so1.RootPart, null, null); // Create a second object SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100); @@ -127,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); m_scene.AddSceneObject(so1); LSL_Api api = new LSL_Api(); - api.Initialize(new ScriptInstance(m_engine, so1.RootPart, null, 0, false, int.MaxValue)); + api.Initialize(m_engine, so1.RootPart, null, null); // Create an object embedded inside the first UUID itemId = TestHelpers.ParseTail(0x20); @@ -137,7 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100); m_scene.AddSceneObject(so2); LSL_Api api2 = new LSL_Api(); - api2.Initialize(new ScriptInstance(m_engine, so2.RootPart, null, 0, false, int.MaxValue)); + api2.Initialize(m_engine, so2.RootPart, null, null); // *** Firstly, we test where llAllowInventoryDrop() has not been called. *** api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs index 51213442cc..5b57bbe497 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs @@ -105,7 +105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(grp2); LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(new ScriptInstance(m_engine, grp1.RootPart, grp1Item, 0, false, int.MaxValue)); + apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null); apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE); @@ -132,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(new ScriptInstance(m_engine, grp1.RootPart, grp1Item, 0, false, int.MaxValue)); + apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null); apiGrp1.llBreakLink(2); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs index 28e58315b1..60de5cb62d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs @@ -68,7 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests engine.AddRegion(scene); m_lslApi = new LSL_Api(); - m_lslApi.Initialize(new ScriptInstance(engine, part, null, 0, false, int.MaxValue)); + m_lslApi.Initialize(engine, part, null, null); } [Test] diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs index 48c2465825..e97ae06a7f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests engine.AddRegion(scene); m_lslApi = new LSL_Api(); - m_lslApi.Initialize(new ScriptInstance(engine, part, null, 0, false, int.MaxValue)); + m_lslApi.Initialize(engine, part, null, null); } [Test] diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index 5164d4e8f1..c88bad5dfc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); string notecardName = "appearanceNc"; @@ -135,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); string notecardName = "appearanceNc"; diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs index e7b3319025..b2803a12c0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs @@ -99,10 +99,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); - ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue); - new LSL_Api().Initialize(si); + new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(si); + osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); // SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID); @@ -146,10 +145,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); - ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue); - new LSL_Api().Initialize(si); + new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(si); + osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); // Create an object embedded inside the first TaskInventoryHelpers.AddNotecard( @@ -195,10 +193,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); - ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue); - new LSL_Api().Initialize(si); + new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(si); + osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null); // Create an object embedded inside the first TaskInventoryHelpers.AddSceneObject( diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 584f44f12a..1f8a6e5b14 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -100,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); string notecardName = "appearanceNc"; osslApi.osOwnerSaveAppearance(notecardName); @@ -126,7 +126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, so.RootPart, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, so.RootPart, null, null); bool gotExpectedException = false; try @@ -161,7 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); string notecardName = "appearanceNc"; osslApi.osOwnerSaveAppearance(notecardName); @@ -195,7 +195,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); osslApi.osOwnerSaveAppearance(firstAppearanceNcName); @@ -233,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); osslApi.osOwnerSaveAppearance(firstAppearanceNcName); @@ -285,10 +285,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(otherSo); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); OSSL_Api otherOsslApi = new OSSL_Api(); - otherOsslApi.Initialize(new ScriptInstance(m_engine, otherPart, null, 0, false, int.MaxValue)); + otherOsslApi.Initialize(m_engine, otherPart, null, null); string notecardName = "appearanceNc"; osslApi.osOwnerSaveAppearance(notecardName); @@ -332,7 +332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_scene.AddSceneObject(so); OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue)); + osslApi.Initialize(m_engine, part, null, null); string notecardName = "appearanceNc"; osslApi.osOwnerSaveAppearance(notecardName); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 186ae041bf..a17a0188bb 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1716,9 +1716,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) + { instance.Stop(m_WaitForEventCompletionOnScriptStop); + } else + { +// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); m_runFlags.AddOrUpdate(itemID, false, 240); + } } public DetectParams GetDetectParams(UUID itemID, int idx) diff --git a/prebuild.xml b/prebuild.xml index c6bef5cbbe..abf8f364d7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2417,7 +2417,9 @@ - + + + @@ -3309,6 +3311,7 @@ + From daef2b8d87300f02bef7edf01ae67c8c6a50af46 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 15 Jan 2013 12:55:55 -0800 Subject: [PATCH 3/8] BulletSim: reduce maximum force a script can apply (like in llApplyImpulse) to the documented maximum from the outragious number previously. --- OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 862dbf6710..3e80aa4101 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -94,16 +94,16 @@ public static class BSParam public static float PID_D { get; private set; } // derivative public static float PID_P { get; private set; } // proportional - // Various constants that come from that other virtual world that shall not be named + // Various constants that come from that other virtual world that shall not be named. public const float MinGravityZ = -1f; public const float MaxGravityZ = 28f; public const float MinFriction = 0f; public const float MaxFriction = 255f; - public const float MinDensity = 0f; + public const float MinDensity = 0.01f; public const float MaxDensity = 22587f; public const float MinRestitution = 0f; public const float MaxRestitution = 1f; - public const float MaxAddForceMagnitude = 20000f; + public const float MaxAddForceMagnitude = 20f; // =========================================================================== public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); From 61ff79587bea373278771f9529b582db2e05afdd Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 15 Jan 2013 12:57:12 -0800 Subject: [PATCH 4/8] BulletSim: add debugging messages to know when assets for physical objects have been fetched. Update TODO list with more work. --- .../Physics/BulletSPlugin/BSCharacter.cs | 5 ++- .../BulletSPlugin/BSLinksetCompound.cs | 4 +- .../BulletSPlugin/BSShapeCollection.cs | 42 ++++++++++++------- .../Physics/BulletSPlugin/BulletSimTODO.txt | 17 ++++++++ 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index a5fec87eed..2e900b367f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -855,7 +855,10 @@ public sealed class BSCharacter : BSPhysObject _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); + if (PositionSanityCheck(true)) + { + entprop.Position = _position; + } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 2dc89b51d3..eff909ca85 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -108,8 +108,8 @@ public sealed class BSLinksetCompound : BSLinkset // Schedule a refresh to happen after all the other taint processing. private void ScheduleRebuild(BSPhysObject requestor) { - DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2}", - requestor.LocalID, Rebuilding, HasAnyChildren); + DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", + requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); // When rebuilding, it is possible to set properties that would normally require a rebuild. // If already rebuilding, don't request another rebuild. // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index addab2955a..4f0d3458dc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -513,6 +513,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } + // return 'true' if the shape was changed public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { @@ -872,8 +873,7 @@ public sealed class BSShapeCollection : IDisposable { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, prim.LocalID, prim.LastAssetBuildFailed); + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; @@ -882,19 +882,34 @@ public sealed class BSShapeCollection : IDisposable BSPhysObject yprim = xprim; // probably not necessary, but, just in case. assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) { - if (!yprim.BaseShape.SculptEntry) - return; - if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) - return; - - yprim.BaseShape.SculptData = asset.Data; - // This will cause the prim to see that the filler shape is not the right - // one and try again to build the object. - // No race condition with the normal shape setting since the rebuild is at taint time. - yprim.ForceBodyShapeRebuild(false); + bool assetFound = false; // DEBUG DEBUG + string mismatchIDs = String.Empty; // DEBUG DEBUG + if (yprim.BaseShape.SculptEntry) + { + if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) + { + yprim.BaseShape.SculptData = asset.Data; + // This will cause the prim to see that the filler shape is not the right + // one and try again to build the object. + // No race condition with the normal shape setting since the rebuild is at taint time. + yprim.ForceBodyShapeRebuild(false /* inTaintTime */); + assetFound = true; + } + else + { + mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; + } + } + DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", + yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); }); } + else + { + PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", + LogHeader, PhysicsScene.Name); + } }); } else @@ -907,8 +922,7 @@ public sealed class BSShapeCollection : IDisposable } // While we figure out the real problem, stick in a simple box for the object. - BulletShape fillinShape = - BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); + BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 59cbab9412..067e64a08f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -1,7 +1,23 @@ CURRENT PRIORITIES ================================================= +Crazyness during 20130115 office hours was PositionAdjustUnderground for both char and prim + m1:logs/20130115.0934/physics-BulletSim-20130115083613.log + Creation of Neb's terrain made the terrain "disappear". Everything started to fall + and then get restored to be above terrain. +Create tests for different interface components + Have test objects/scripts measure themselves and turn color if correct/bad + Test functions in SL and calibrate correctness there + Create auto rezzer and tracker to run through the tests +Mantis 6040 script http://opensimulator.org/mantis/view.php?id=6040 + Msg Kayaker on OSGrid when working +Teravus llMoveToTarget script debug + Mixing of hover, buoyancy/gravity, moveToTarget, into one force +Surf board debugging +Boats floating at proper level Nebadon vehicles turning funny in arena limitMotorUp calibration (more down?) +llRotLookAt +llLookAt Vehicle angular vertical attraction Vehicle angular deflection Preferred orientation angular correction fix @@ -167,6 +183,7 @@ Enforce physical parameter min/max: Restitution [0, 1] http://wiki.secondlife.com/wiki/Physics_Material_Settings_test Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/31796/1.html +Keep avatar scaling correct. http://pennycow.blogspot.fr/2011/07/matter-of-scale.html INTERNAL IMPROVEMENT/CLEANUP ================================================= From 5d098d8f17fe24d9ad2999ddce819787d02989ce Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 15 Jan 2013 15:07:38 -0800 Subject: [PATCH 5/8] BulletSim: don't modify angular parameters when doing LIMIT_MOTOR_UP. It was a dumb idea to try and do a nose over feature for jumping cars anyway. Add better logging of native shape creation/reuse so can tell the difference. --- .../Physics/BulletSPlugin/BSCharacter.cs | 2 +- .../Physics/BulletSPlugin/BSDynamics.cs | 12 +++++----- .../BulletSPlugin/BSLinksetCompound.cs | 2 +- .../BulletSPlugin/BSShapeCollection.cs | 18 +++++++------- .../Physics/BulletSPlugin/BulletSimTODO.txt | 24 +++++++++---------- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e900b367f..87a06c1453 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -215,7 +215,7 @@ public sealed class BSCharacter : BSPhysObject // Add special movement force to allow avatars to walk up stepped surfaces. moveForce += WalkUpStairs(); - DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); + // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); }); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index e434412017..6601479d62 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -1160,8 +1160,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (!Prim.IsColliding && VehicleVelocity.Z > 0.1) { // Get rid of any of the velocity vector that is pushing us up. - VehicleVelocity += new Vector3(0, 0, -VehicleVelocity.Z); + float upVelocity = VehicleVelocity.Z; + VehicleVelocity += new Vector3(0, 0, -upVelocity); + /* // If we're pointed up into the air, we should nose down Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; // The rotation around the Y axis is pitch up or down @@ -1175,11 +1177,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}", Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector); } - else - { - VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2}", - Prim.LocalID, VehicleVelocity, pointingDirection); - } + */ + VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", + Prim.LocalID, Prim.IsColliding, upVelocity, VehicleVelocity); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index eff909ca85..8c9a7745f0 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -311,7 +311,7 @@ public sealed class BSLinksetCompound : BSLinkset else { // Rebuild the compound shape with the child removed - ScheduleRebuild(child); + ScheduleRebuild(LinksetRoot); } } return; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 4f0d3458dc..9fbfcdcabc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -442,7 +442,8 @@ public sealed class BSShapeCollection : IDisposable return ret; } - // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. + // Create a mesh, hull or native shape. + // Return 'true' if the prim's shape was changed. public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) { bool ret = false; @@ -472,7 +473,7 @@ public sealed class BSShapeCollection : IDisposable if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); - // It doesn't look like Bullet scales spheres so make sure the scales are all equal + // It doesn't look like Bullet scales native spheres so make sure the scales are all equal if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) { @@ -484,9 +485,9 @@ public sealed class BSShapeCollection : IDisposable { ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); } + if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", + prim.LocalID, forceRebuild, ret, prim.PhysShape); } if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) { @@ -498,9 +499,9 @@ public sealed class BSShapeCollection : IDisposable { ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); } + if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", + prim.LocalID, forceRebuild, ret, prim.PhysShape); } } @@ -513,7 +514,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } - // return 'true' if the shape was changed + // return 'true' if the prim's shape was changed. public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { @@ -921,8 +922,9 @@ public sealed class BSShapeCollection : IDisposable } } - // While we figure out the real problem, stick in a simple box for the object. + // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 067e64a08f..53b553073e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -1,18 +1,9 @@ CURRENT PRIORITIES ================================================= -Crazyness during 20130115 office hours was PositionAdjustUnderground for both char and prim - m1:logs/20130115.0934/physics-BulletSim-20130115083613.log - Creation of Neb's terrain made the terrain "disappear". Everything started to fall - and then get restored to be above terrain. -Create tests for different interface components - Have test objects/scripts measure themselves and turn color if correct/bad - Test functions in SL and calibrate correctness there - Create auto rezzer and tracker to run through the tests Mantis 6040 script http://opensimulator.org/mantis/view.php?id=6040 Msg Kayaker on OSGrid when working Teravus llMoveToTarget script debug Mixing of hover, buoyancy/gravity, moveToTarget, into one force -Surf board debugging Boats floating at proper level Nebadon vehicles turning funny in arena limitMotorUp calibration (more down?) @@ -25,8 +16,6 @@ vehicle angular banking Avatars walking up stairs (HALF DONE) Radius of the capsule affects ability to climb edges. Vehicle movement on terrain smoothness -Surfboard go wonky when turning - Angular motor direction is global coordinates rather than local coordinates? Boats float low in the water (DONE) Avatar movement flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) @@ -43,6 +32,10 @@ Add material densities to the material types CRASHES ================================================= +Crazyness during 20130115 office hours was PositionAdjustUnderground for both char and prim + m1:logs/20130115.0934/physics-BulletSim-20130115083613.log + Creation of Neb's terrain made the terrain "disappear". Everything started to fall + and then get restored to be above terrain. 20121129.1411: editting/moving phys object across region boundries causes crash getPos-> btRigidBody::upcast -> getBodyType -> BOOM 20121128.1600: mesh object not rezzing (no physics mesh). @@ -149,6 +142,10 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint) MORE ====================================================== +Create tests for different interface components + Have test objects/scripts measure themselves and turn color if correct/bad + Test functions in SL and calibrate correctness there + Create auto rezzer and tracker to run through the tests Use the HACD convex hull routine in Bullet rather than the C# version. Do we need to do convex hulls all the time? Can complex meshes be left meshes? There is some problem with meshes and collisions @@ -304,4 +301,7 @@ Disable activity of passive linkset children. (DONE) Since the linkset is a compound object, the old prims are left lying around and need to be phantomized so they don't collide, ... Remove HeightmapInfo from terrain specification (DONE) - Since C++ code does not need terrain height, this structure et al are not needed. \ No newline at end of file + Since C++ code does not need terrain height, this structure et al are not needed. +Surfboard go wonky when turning (DONE) + Angular motor direction is global coordinates rather than local coordinates? + (Resolution: made angular motor direction correct coordinate system) \ No newline at end of file From 8ee9daa121440ad550676814fe60e6b6c0c5d701 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 15 Jan 2013 21:08:11 -0800 Subject: [PATCH 6/8] BulletSim: add the editting children in linkset going phantom bug to TODO list. --- OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 53b553073e..d4545f7ffc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -120,6 +120,8 @@ Physical and phantom will drop through the terrain LINKSETS ====================================================== +Editing a child of a linkset causes the child to go phantom + Move a child prim once when it is physical and can never move it again without it going phantom Offset the center of the linkset to be the geometric center of all the prims Not quite the same as the center-of-gravity Linksets should allow collisions to individual children From 37fcf87946df0cc6824063aa42853048ca4238c9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 16 Jan 2013 08:20:32 -0800 Subject: [PATCH 7/8] Changed a couple of debug messages at the request of osgrid. --- .../Framework/EntityTransfer/HGEntityTransferModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 41ca13b8ea..b1887418ee 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -212,11 +212,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override GridRegion GetFinalDestination(GridRegion region) { int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionName, flags); if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region is hyperlink"); GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); if (real_destination != null) m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); From 5563a8916ed5c78f91dccb668453f5782ab19532 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 16:45:18 +0000 Subject: [PATCH 8/8] Complete removal of the now unused state queue --- OpenSim/Framework/ThrottleOutPacketType.cs | 4 ---- .../ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../ClientStack/Linden/UDP/LLUDPClient.cs | 17 +++-------------- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index d56231a397..ca4b126c97 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs @@ -47,9 +47,6 @@ namespace OpenSim.Framework Texture = 5, /// Non-texture assets Asset = 6, - /// Avatar and primitive data - /// This is a sub-category of Task - State = 7, } [Flags] @@ -61,6 +58,5 @@ namespace OpenSim.Framework Task = 1 << 3, Texture = 1 << 4, Asset = 1 << 5, - State = 1 << 6, } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a8517e60f3..77acacf299 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1588,7 +1588,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) { - OutPacket(kill, ThrottleOutPacketType.State); + OutPacket(kill, ThrottleOutPacketType.Task); } else { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 8963756dcc..621e0fd1ff 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -278,7 +278,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public string GetStats() { return string.Format( - "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}", + "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", Util.EnvironmentTickCountSubtract(TickLastPacketReceived), PacketsReceived, PacketsSent, @@ -290,8 +290,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_packetOutboxes[(int)ThrottleOutPacketType.Cloud].Count, m_packetOutboxes[(int)ThrottleOutPacketType.Task].Count, m_packetOutboxes[(int)ThrottleOutPacketType.Texture].Count, - m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count, - m_packetOutboxes[(int)ThrottleOutPacketType.State].Count); + m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count); } public void SendPacketStats() @@ -337,8 +336,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); - // State is a subcategory of task that we allocate a percentage to - int state = 0; // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged @@ -375,9 +372,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; bucket.RequestedDripRate = task; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.State]; - bucket.RequestedDripRate = state; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; bucket.RequestedDripRate = texture; @@ -678,9 +672,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP Texture = 5, /// Non-texture assets Asset = 6, - /// Avatar and primitive data - /// This is a sub-category of Task - State = 7, */ switch (category) @@ -697,11 +688,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP return ThrottleOutPacketTypeFlags.Texture; case ThrottleOutPacketType.Asset: return ThrottleOutPacketTypeFlags.Asset; - case ThrottleOutPacketType.State: - return ThrottleOutPacketTypeFlags.State; default: return 0; } } } -} \ No newline at end of file +}