From 746829967315cc82560a855a4772e45888bf8fbe Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 3 Apr 2012 05:50:13 +0100 Subject: Eliminate race condition where many callers would check SOP.PhysicsActor != null then assume it was still not null in later code. Another thread could come and turn off physics for a part (null PhysicsActor) at any point. Had to turn off localCopy on warp3D CoreModules section in prebuild.xml since on current nant this copies all DLLs in bin/ which can be a very large number with compiled DLLs No obvious reason for doing that copy - nothing else does it. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 207 ++++++++++++--------- 1 file changed, 116 insertions(+), 91 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 439b718..2b1fba0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -151,6 +151,14 @@ namespace OpenSim.Region.Framework.Scenes public int[] PayPrice = {-2,-2,-2,-2,-2}; [XmlIgnore] + /// + /// The representation of this part in the physics scene. + /// + /// + /// If you use this property more than once in a section of code then you must take a reference and use that. + /// If another thread is simultaneously turning physics off on this part then this refernece could become + /// null at any time. + /// public PhysicsActor PhysActor { get { return m_physActor; } @@ -522,10 +530,11 @@ namespace OpenSim.Region.Framework.Scenes set { m_name = value; - if (PhysActor != null) - { - PhysActor.SOPName = value; - } + + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.SOPName = value; } } @@ -535,10 +544,11 @@ namespace OpenSim.Region.Framework.Scenes set { m_material = (Material)value; - if (PhysActor != null) - { - PhysActor.SetMaterial((int)value); - } + + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.SetMaterial((int)value); } } @@ -669,9 +679,7 @@ namespace OpenSim.Region.Framework.Scenes // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; if (actor != null && ParentID == 0) - { m_groupPosition = actor.Position; - } if (ParentGroup.IsAttachment) { @@ -979,7 +987,7 @@ namespace OpenSim.Region.Framework.Scenes if (Shape.SculptEntry) CheckSculptAndLoad(); else - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); } } } @@ -1505,12 +1513,14 @@ namespace OpenSim.Region.Framework.Scenes } // Basic Physics can also return null as well as an exception catch. - if (PhysActor != null) + PhysicsActor pa = PhysActor; + + if (pa != null) { - PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info - PhysActor.SetMaterial(Material); + pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info + pa.SetMaterial(Material); DoPhysicsPropertyUpdate(RigidBody, true); - PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); + pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0); } } } @@ -1731,23 +1741,25 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (PhysActor != null) + PhysicsActor pa = PhysActor; + + if (pa != null) { - if (UsePhysics != PhysActor.IsPhysical || isNew) + if (UsePhysics != pa.IsPhysical || isNew) { - if (PhysActor.IsPhysical) // implies UsePhysics==false for this block + if (pa.IsPhysical) // implies UsePhysics==false for this block { if (!isNew) ParentGroup.Scene.RemovePhysicalPrim(1); - PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; - PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; - PhysActor.delink(); + pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; + pa.OnOutOfBounds -= PhysicsOutOfBounds; + pa.delink(); if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) { // destroy all joints connected to this now deactivated body - ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor); + ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); } // stop client-side interpolation of all joint proxy objects that have just been deleted @@ -1766,7 +1778,7 @@ namespace OpenSim.Region.Framework.Scenes //RotationalVelocity = new Vector3(0, 0, 0); } - PhysActor.IsPhysical = UsePhysics; + pa.IsPhysical = UsePhysics; // If we're not what we're supposed to be in the physics scene, recreate ourselves. //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); @@ -1779,13 +1791,15 @@ namespace OpenSim.Region.Framework.Scenes { ParentGroup.Scene.AddPhysicalPrim(1); - PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; - PhysActor.OnOutOfBounds += PhysicsOutOfBounds; + pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; + pa.OnOutOfBounds += PhysicsOutOfBounds; if (ParentID != 0 && ParentID != LocalId) { - if (ParentGroup.RootPart.PhysActor != null) + PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; + + if (parentPa != null) { - PhysActor.link(ParentGroup.RootPart.PhysActor); + pa.link(parentPa); } } } @@ -1797,7 +1811,7 @@ namespace OpenSim.Region.Framework.Scenes if (Shape.SculptEntry) CheckSculptAndLoad(); else - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); } } } @@ -1908,24 +1922,30 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 GetGeometricCenter() { - if (PhysActor != null) - return new Vector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); + PhysicsActor pa = PhysActor; + + if (pa != null) + return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); else return new Vector3(0, 0, 0); } public float GetMass() { - if (PhysActor != null) - return PhysActor.Mass; + PhysicsActor pa = PhysActor; + + if (pa != null) + return pa.Mass; else return 0; } public Vector3 GetForce() { - if (PhysActor != null) - return PhysActor.Force; + PhysicsActor pa = PhysActor; + + if (pa != null) + return pa.Force; else return Vector3.Zero; } @@ -2556,9 +2576,11 @@ namespace OpenSim.Region.Framework.Scenes public void PhysicsRequestingTerseUpdate() { - if (PhysActor != null) + PhysicsActor pa = PhysActor; + + if (pa != null) { - Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); + Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) @@ -2570,6 +2592,7 @@ namespace OpenSim.Region.Framework.Scenes } //ParentGroup.RootPart.m_groupPosition = newpos; } + ScheduleTerseUpdate(); } @@ -2660,7 +2683,9 @@ namespace OpenSim.Region.Framework.Scenes scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); - if (PhysActor != null && PhysActor.IsPhysical) + PhysicsActor pa = PhysActor; + + if (pa != null && pa.IsPhysical) { scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); @@ -2809,12 +2834,14 @@ namespace OpenSim.Region.Framework.Scenes m_shape.SculptData = texture.Data; } - if (PhysActor != null) + PhysicsActor pa = PhysActor; + + if (pa != null) { // Update the physics actor with the new loaded sculpt data and set the taint signal. - PhysActor.Shape = m_shape; + pa.Shape = m_shape; - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); } } } @@ -3072,10 +3099,10 @@ namespace OpenSim.Region.Framework.Scenes public void SetBuoyancy(float fvalue) { - if (PhysActor != null) - { - PhysActor.Buoyancy = fvalue; - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.Buoyancy = fvalue; } public void SetDieAtEdge(bool p) @@ -3088,57 +3115,50 @@ namespace OpenSim.Region.Framework.Scenes public void SetFloatOnWater(int floatYN) { - if (PhysActor != null) - { - if (floatYN == 1) - { - PhysActor.FloatOnWater = true; - } - else - { - PhysActor.FloatOnWater = false; - } - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.FloatOnWater = floatYN == 1; } public void SetForce(Vector3 force) { - if (PhysActor != null) - { - PhysActor.Force = force; - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.Force = force; } public void SetVehicleType(int type) { - if (PhysActor != null) - { - PhysActor.VehicleType = type; - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.VehicleType = type; } public void SetVehicleFloatParam(int param, float value) { - if (PhysActor != null) - { - PhysActor.VehicleFloatParam(param, value); - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.VehicleFloatParam(param, value); } public void SetVehicleVectorParam(int param, Vector3 value) { - if (PhysActor != null) - { - PhysActor.VehicleVectorParam(param, value); - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.VehicleVectorParam(param, value); } public void SetVehicleRotationParam(int param, Quaternion rotation) { - if (PhysActor != null) - { - PhysActor.VehicleRotationParam(param, rotation); - } + PhysicsActor pa = PhysActor; + + if (pa != null) + pa.VehicleRotationParam(param, rotation); } /// @@ -4226,6 +4246,8 @@ namespace OpenSim.Region.Framework.Scenes if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) return; + PhysicsActor pa = PhysActor; + // Special cases for VD. VD can only be called from a script // and can't be combined with changes to other states. So we can rely // that... @@ -4241,8 +4263,9 @@ namespace OpenSim.Region.Framework.Scenes { SetVD = false; // Switch it of for the course of this routine VolumeDetectActive = false; // and also permanently - if (PhysActor != null) - PhysActor.SetVolumeDetect(0); // Let physics know about it too + + if (pa != null) + pa.SetVolumeDetect(0); // Let physics know about it too } else { @@ -4357,9 +4380,9 @@ namespace OpenSim.Region.Framework.Scenes // Defensive programming calls for a check here. // Better would be throwing an exception that could be catched by a unit test as the internal // logic should make sure, this Physactor is always here. - if (this.PhysActor != null) + if (pa != null) { - PhysActor.SetVolumeDetect(1); + pa.SetVolumeDetect(1); AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active this.VolumeDetectActive = true; } @@ -4368,11 +4391,8 @@ namespace OpenSim.Region.Framework.Scenes { // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like // (mumbles, well, at least if you have infinte CPU powers :-)) - PhysicsActor pa = this.PhysActor; if (pa != null) - { PhysActor.SetVolumeDetect(0); - } this.VolumeDetectActive = false; } @@ -4385,6 +4405,7 @@ namespace OpenSim.Region.Framework.Scenes { RemFlag(PrimFlags.TemporaryOnRez); } + // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); if (ParentGroup != null) @@ -4453,10 +4474,12 @@ namespace OpenSim.Region.Framework.Scenes m_shape.PathTwist = shapeBlock.PathTwist; m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; - if (PhysActor != null) + PhysicsActor pa = PhysActor; + + if (pa != null) { - PhysActor.Shape = m_shape; - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + pa.Shape = m_shape; + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); } // This is what makes vehicle trailers work @@ -4598,6 +4621,8 @@ namespace OpenSim.Region.Framework.Scenes objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; } + PhysicsActor pa = PhysActor; + if ( ((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || @@ -4609,18 +4634,18 @@ namespace OpenSim.Region.Framework.Scenes ) { // subscribe to physics updates. - if (PhysActor != null) + if (pa != null) { - PhysActor.OnCollisionUpdate += PhysicsCollision; - PhysActor.SubscribeEvents(1000); + pa.OnCollisionUpdate += PhysicsCollision; + pa.SubscribeEvents(1000); } } else { - if (PhysActor != null) + if (pa != null) { - PhysActor.UnSubscribeEvents(); - PhysActor.OnCollisionUpdate -= PhysicsCollision; + pa.UnSubscribeEvents(); + pa.OnCollisionUpdate -= PhysicsCollision; } } -- cgit v1.1