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.iar_mods
							parent
							
								
									45c7789b54
								
							
						
					
					
						commit
						e16d7fe1da
					
				| 
						 | 
				
			
			@ -219,9 +219,14 @@ namespace OpenSim.Region.Physics.OdePlugin
 | 
			
		|||
        private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// A list of actors that should receive collision events.
 | 
			
		||||
        /// A dictionary of actors that should receive collision events.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// A dictionary of collision event changes that are waiting to be processed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>();
 | 
			
		||||
        
 | 
			
		||||
        private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
 | 
			
		||||
        public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
 | 
			
		||||
| 
						 | 
				
			
			@ -1635,8 +1640,8 @@ namespace OpenSim.Region.Physics.OdePlugin
 | 
			
		|||
        {
 | 
			
		||||
//            m_log.DebugFormat("[PHYSICS]: Adding {0} to collision event reporting", obj.SOPName);
 | 
			
		||||
            
 | 
			
		||||
            lock (_collisionEventPrim)
 | 
			
		||||
                _collisionEventPrim[obj.LocalID] = obj;
 | 
			
		||||
            lock (_collisionEventPrimChanges)
 | 
			
		||||
                _collisionEventPrimChanges[obj.LocalID] = obj;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -1647,8 +1652,8 @@ namespace OpenSim.Region.Physics.OdePlugin
 | 
			
		|||
        {
 | 
			
		||||
//            m_log.DebugFormat("[PHYSICS]: Removing {0} from collision event reporting", obj.SOPName);
 | 
			
		||||
 | 
			
		||||
            lock (_collisionEventPrim)
 | 
			
		||||
                _collisionEventPrim.Remove(obj.LocalID);
 | 
			
		||||
            lock (_collisionEventPrimChanges)
 | 
			
		||||
                _collisionEventPrimChanges[obj.LocalID] = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Add/Remove Entities
 | 
			
		||||
| 
						 | 
				
			
			@ -2660,6 +2665,22 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
 | 
			
		|||
//                m_physicsiterations = 10;
 | 
			
		||||
//            }
 | 
			
		||||
 | 
			
		||||
            // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
 | 
			
		||||
            // deadlock if the collision event tries to lock something else later on which is already locked by a
 | 
			
		||||
            // caller that is adding or removing the collision event.
 | 
			
		||||
            lock (_collisionEventPrimChanges)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (KeyValuePair<uint, PhysicsActor> kvp in _collisionEventPrimChanges)
 | 
			
		||||
                {
 | 
			
		||||
                    if (kvp.Value == null)
 | 
			
		||||
                        _collisionEventPrim.Remove(kvp.Key);
 | 
			
		||||
                    else
 | 
			
		||||
                        _collisionEventPrim[kvp.Key] = kvp.Value;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                _collisionEventPrimChanges.Clear();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (SupportsNINJAJoints)
 | 
			
		||||
            {
 | 
			
		||||
                DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
 | 
			
		||||
| 
						 | 
				
			
			@ -2787,25 +2808,22 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
 | 
			
		|||
 | 
			
		||||
                        collision_optimized();
 | 
			
		||||
 | 
			
		||||
                        lock (_collisionEventPrim)
 | 
			
		||||
                        foreach (PhysicsActor obj in _collisionEventPrim.Values)
 | 
			
		||||
                        {
 | 
			
		||||
                            foreach (PhysicsActor obj in _collisionEventPrim.Values)
 | 
			
		||||
                            {
 | 
			
		||||
//                                m_log.DebugFormat("[PHYSICS]: Assessing {0} for collision events", obj.SOPName);
 | 
			
		||||
 | 
			
		||||
                                switch ((ActorTypes)obj.PhysicsActorType)
 | 
			
		||||
                                {
 | 
			
		||||
                                    case ActorTypes.Agent:
 | 
			
		||||
                                        OdeCharacter cobj = (OdeCharacter)obj;
 | 
			
		||||
                                        cobj.AddCollisionFrameTime(100);
 | 
			
		||||
                                        cobj.SendCollisions();
 | 
			
		||||
                                        break;
 | 
			
		||||
                            switch ((ActorTypes)obj.PhysicsActorType)
 | 
			
		||||
                            {
 | 
			
		||||
                                case ActorTypes.Agent:
 | 
			
		||||
                                    OdeCharacter cobj = (OdeCharacter)obj;
 | 
			
		||||
                                    cobj.AddCollisionFrameTime(100);
 | 
			
		||||
                                    cobj.SendCollisions();
 | 
			
		||||
                                    break;
 | 
			
		||||
 | 
			
		||||
                                    case ActorTypes.Prim:
 | 
			
		||||
                                        OdePrim pobj = (OdePrim)obj;
 | 
			
		||||
                                        pobj.SendCollisions();
 | 
			
		||||
                                        break;
 | 
			
		||||
                                }
 | 
			
		||||
                                case ActorTypes.Prim:
 | 
			
		||||
                                    OdePrim pobj = (OdePrim)obj;
 | 
			
		||||
                                    pobj.SendCollisions();
 | 
			
		||||
                                    break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue