From fdb7a804fcbcddec0e2f2edc15ad1ede1bfee2aa Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 2 Aug 2015 22:31:53 -0700 Subject: Add an option to processes physics collisions using FireAndForget. Off by default but set with [Startup]ShouldUseFireAndForgetForCollsions=true There is a problem with physics colliions sometimes stopping. One suspicion is that the long callback path from the physics engine into the script engine is causing problems. Enabling this feature passes the collision into the script engine on a separate thread and not the main simulation thread. Tester can enable this and see if the collsions stay around. If they still fail, this commit should be reverted and another solution looked for. --- OpenSim/Region/Framework/Scenes/Scene.cs | 17 +++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 ++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b876fc6..2a69ee1 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -423,6 +423,17 @@ namespace OpenSim.Region.Framework.Scenes private int landMS; private int spareMS; + // A temporary configuration flag to enable using FireAndForget to process + // collisions from the physics engine. There is a problem with collisions + // stopping sometimes and MB's suspicion is some race condition passing + // collisions from the physics engine callback to the script engine. + // This causes the collision events to be passed with a FireAndForget + // call which should eliminate that linkage. Testers can turn this on + // and see if collisions stop. If they don't, the problem is somewhere else. + // This feature defaults to 'off' so, by default, the simulator operation + // is not changed. + public bool ShouldUseFireAndForgetForCollisions = false; + /// /// Tick at which the last frame was processed. /// @@ -1075,8 +1086,14 @@ namespace OpenSim.Region.Framework.Scenes m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences); m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); + + if (startupConfig.Contains("ShouldUseFireAndForgetForCollisions")) + { + ShouldUseFireAndForgetForCollisions = startupConfig.GetBoolean("ShouldUseFireAndForgetForCollisions", false); + } } + // FIXME: Ultimately this should be in a module. SendPeriodicAppearanceUpdates = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 781c20c..f52c9c8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -126,6 +126,8 @@ namespace OpenSim.Region.Framework.Scenes private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private bool shouldUseFireAndForgetForCollisions = true; + /// /// Dynamic attributes can be created and deleted as required. /// @@ -2392,7 +2394,7 @@ namespace OpenSim.Region.Framework.Scenes CollidingMessage = CreateColliderArgs(this, colliders); if (CollidingMessage.Colliders.Count > 0) - notify(LocalId, CollidingMessage); + DoNotify(notify, LocalId, CollidingMessage); if (PassCollisions) sendToRoot = true; @@ -2406,7 +2408,7 @@ namespace OpenSim.Region.Framework.Scenes { CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); if (CollidingMessage.Colliders.Count > 0) - notify(ParentGroup.RootPart.LocalId, CollidingMessage); + DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); } } } @@ -2421,7 +2423,33 @@ namespace OpenSim.Region.Framework.Scenes colliding.Add(CreateDetObjectForGround()); LandCollidingMessage.Colliders = colliding; - notify(LocalId, LandCollidingMessage); + DoNotify(notify, LocalId, LandCollidingMessage); + } + } + + private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) + { + if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions) + { + // For those learning C#, FireAndForget takes a function, an object to pass + // to that function and an ID string. The "oo => {}" construct is a lambda expression + // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object + // that is an object array and initializes it with three items (the parameters + // being passed). The parameters passed are the function to call ('notify') and + // its two arguements. Finally, once in the function (called later by the FireAndForget + // thread scheduler), the passed object is cast to an object array and then each + // of its items (aoo[0] to aoo[2]) are individually cast to what they are and + // then used in a call of the passed ScriptCollidingNotification function. + Util.FireAndForget(oo => + { + Object[] aoo = (Object[])oo; + ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]); + + }, new Object[] { notify, id, collargs }, "SOP.Collision"); + } + else + { + notify(id, collargs); } } -- cgit v1.1