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