aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2011-11-15 20:02:09 +0000
committerJustin Clark-Casey (justincc)2011-11-15 20:02:09 +0000
commite16d7fe1da3432d819f72e8c2af420601009854b (patch)
tree3be42d6810fec53e599f50cd7ea34e870a40af51
parentuse a more efficient dictionary in OdeScene._collisionEventPrim rather than a... (diff)
downloadopensim-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.cs58
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