diff options
author | Justin Clark-Casey (justincc) | 2011-11-15 20:02:09 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2011-11-15 20:02:09 +0000 |
commit | e16d7fe1da3432d819f72e8c2af420601009854b (patch) | |
tree | 3be42d6810fec53e599f50cd7ea34e870a40af51 | |
parent | use a more efficient dictionary in OdeScene._collisionEventPrim rather than a... (diff) | |
download | opensim-SC_OLD-e16d7fe1da3432d819f72e8c2af420601009854b.zip opensim-SC_OLD-e16d7fe1da3432d819f72e8c2af420601009854b.tar.gz opensim-SC_OLD-e16d7fe1da3432d819f72e8c2af420601009854b.tar.bz2 opensim-SC_OLD-e16d7fe1da3432d819f72e8c2af420601009854b.tar.xz |
Instead of having scene add/remove collision events directly to the OdeScene collision event dictionary, marshall them via a change dictionary first.
This is to avoid a complicated tri-thread deadlock on region crossing for avatars with attachments, where
1) XEngine starting up scripts can lock XEngine.m_Scripts and then try to lock OdeScene._collisionEventPrim while starting up a script due to avatar border crossing
2) An existing collision event will lock OdeScene._collisionEventPrim and then try to lock SP.m_attachments while trying to send the collision event to attachments
3) The avatar still entering the region will lock SP.m_attachments and then try to lock m_Scripts to start more attachment scripts.
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index a4e5c1e..740037f 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -219,9 +219,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
219 | private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); | 219 | private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); |
220 | 220 | ||
221 | /// <summary> | 221 | /// <summary> |
222 | /// A list of actors that should receive collision events. | 222 | /// A dictionary of actors that should receive collision events. |
223 | /// </summary> | 223 | /// </summary> |
224 | private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>(); | 224 | private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>(); |
225 | |||
226 | /// <summary> | ||
227 | /// A dictionary of collision event changes that are waiting to be processed. | ||
228 | /// </summary> | ||
229 | private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); | ||
225 | 230 | ||
226 | private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); | 231 | private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); |
227 | public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); | 232 | public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); |
@@ -1635,8 +1640,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1635 | { | 1640 | { |
1636 | // m_log.DebugFormat("[PHYSICS]: Adding {0} to collision event reporting", obj.SOPName); | 1641 | // m_log.DebugFormat("[PHYSICS]: Adding {0} to collision event reporting", obj.SOPName); |
1637 | 1642 | ||
1638 | lock (_collisionEventPrim) | 1643 | lock (_collisionEventPrimChanges) |
1639 | _collisionEventPrim[obj.LocalID] = obj; | 1644 | _collisionEventPrimChanges[obj.LocalID] = obj; |
1640 | } | 1645 | } |
1641 | 1646 | ||
1642 | /// <summary> | 1647 | /// <summary> |
@@ -1647,8 +1652,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1647 | { | 1652 | { |
1648 | // m_log.DebugFormat("[PHYSICS]: Removing {0} from collision event reporting", obj.SOPName); | 1653 | // m_log.DebugFormat("[PHYSICS]: Removing {0} from collision event reporting", obj.SOPName); |
1649 | 1654 | ||
1650 | lock (_collisionEventPrim) | 1655 | lock (_collisionEventPrimChanges) |
1651 | _collisionEventPrim.Remove(obj.LocalID); | 1656 | _collisionEventPrimChanges[obj.LocalID] = null; |
1652 | } | 1657 | } |
1653 | 1658 | ||
1654 | #region Add/Remove Entities | 1659 | #region Add/Remove Entities |
@@ -2660,6 +2665,22 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); | |||
2660 | // m_physicsiterations = 10; | 2665 | // m_physicsiterations = 10; |
2661 | // } | 2666 | // } |
2662 | 2667 | ||
2668 | // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential | ||
2669 | // deadlock if the collision event tries to lock something else later on which is already locked by a | ||
2670 | // caller that is adding or removing the collision event. | ||
2671 | lock (_collisionEventPrimChanges) | ||
2672 | { | ||
2673 | foreach (KeyValuePair<uint, PhysicsActor> kvp in _collisionEventPrimChanges) | ||
2674 | { | ||
2675 | if (kvp.Value == null) | ||
2676 | _collisionEventPrim.Remove(kvp.Key); | ||
2677 | else | ||
2678 | _collisionEventPrim[kvp.Key] = kvp.Value; | ||
2679 | } | ||
2680 | |||
2681 | _collisionEventPrimChanges.Clear(); | ||
2682 | } | ||
2683 | |||
2663 | if (SupportsNINJAJoints) | 2684 | if (SupportsNINJAJoints) |
2664 | { | 2685 | { |
2665 | DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks | 2686 | DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks |
@@ -2787,25 +2808,22 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); | |||
2787 | 2808 | ||
2788 | collision_optimized(); | 2809 | collision_optimized(); |
2789 | 2810 | ||
2790 | lock (_collisionEventPrim) | 2811 | foreach (PhysicsActor obj in _collisionEventPrim.Values) |
2791 | { | 2812 | { |
2792 | foreach (PhysicsActor obj in _collisionEventPrim.Values) | ||
2793 | { | ||
2794 | // m_log.DebugFormat("[PHYSICS]: Assessing {0} for collision events", obj.SOPName); | 2813 | // m_log.DebugFormat("[PHYSICS]: Assessing {0} for collision events", obj.SOPName); |
2795 | 2814 | ||
2796 | switch ((ActorTypes)obj.PhysicsActorType) | 2815 | switch ((ActorTypes)obj.PhysicsActorType) |
2797 | { | 2816 | { |
2798 | case ActorTypes.Agent: | 2817 | case ActorTypes.Agent: |
2799 | OdeCharacter cobj = (OdeCharacter)obj; | 2818 | OdeCharacter cobj = (OdeCharacter)obj; |
2800 | cobj.AddCollisionFrameTime(100); | 2819 | cobj.AddCollisionFrameTime(100); |
2801 | cobj.SendCollisions(); | 2820 | cobj.SendCollisions(); |
2802 | break; | 2821 | break; |
2803 | 2822 | ||
2804 | case ActorTypes.Prim: | 2823 | case ActorTypes.Prim: |
2805 | OdePrim pobj = (OdePrim)obj; | 2824 | OdePrim pobj = (OdePrim)obj; |
2806 | pobj.SendCollisions(); | 2825 | pobj.SendCollisions(); |
2807 | break; | 2826 | break; |
2808 | } | ||
2809 | } | 2827 | } |
2810 | } | 2828 | } |
2811 | 2829 | ||