diff options
author | Justin Clark-Casey (justincc) | 2012-01-25 19:31:50 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-01-25 19:31:50 +0000 |
commit | e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac (patch) | |
tree | 5a378b0ea1a3c52b7ec16a5be48a2400ee0defc6 | |
parent | Make errors reported by OpenSim when it halts because it can't find certain c... (diff) | |
download | opensim-SC-e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac.zip opensim-SC-e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac.tar.gz opensim-SC-e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac.tar.bz2 opensim-SC-e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac.tar.xz |
Serialize calls to ODE Collide() function across OdeScene instances to prevent ODE crashes on simulators running more than one region.
It turns out that calls to Collide() are not thread-safe even for objects in different ODE physics worlds due to ODE static caches.
For simulators running multiple regions, not serializing calls from different scene loops will sooner or later cause OpenSim to crash with a native stack trace referencing OBBCollider.
This affects the default OPCODE collider but not GIMPACT. However, GIMPACT fails for other reasons under some current simulator loads.
ODE provides a thread local storage option, but as of ODE r1755 (and r1840) DLLs compiled with this crash OpenSim immediately.
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 30 |
2 files changed, 32 insertions, 1 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c6e8286..7c1c046 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | |||
@@ -1048,6 +1048,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1048 | CAPSULE_RADIUS = 0.01f; | 1048 | CAPSULE_RADIUS = 0.01f; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | // lock (OdeScene.UniversalColliderSyncObject) | ||
1051 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); | 1052 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); |
1052 | 1053 | ||
1053 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); | 1054 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); |
@@ -1179,7 +1180,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1179 | 1180 | ||
1180 | if (Shell != IntPtr.Zero) | 1181 | if (Shell != IntPtr.Zero) |
1181 | { | 1182 | { |
1183 | // lock (OdeScene.UniversalColliderSyncObject) | ||
1182 | d.GeomDestroy(Shell); | 1184 | d.GeomDestroy(Shell); |
1185 | |||
1183 | _parent_scene.geom_name_map.Remove(Shell); | 1186 | _parent_scene.geom_name_map.Remove(Shell); |
1184 | _parent_scene.actor_name_map.Remove(Shell); | 1187 | _parent_scene.actor_name_map.Remove(Shell); |
1185 | 1188 | ||
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 37daf46..4530c09 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -105,6 +105,32 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
105 | private readonly ILog m_log; | 105 | private readonly ILog m_log; |
106 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); | 106 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); |
107 | 107 | ||
108 | /// <summary> | ||
109 | /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances. | ||
110 | /// </summary> | ||
111 | /// <remarks> | ||
112 | /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a | ||
113 | /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts | ||
114 | /// uses a static cache at the ODE level. | ||
115 | /// | ||
116 | /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar | ||
117 | /// to | ||
118 | /// | ||
119 | /// mono() [0x489171] | ||
120 | /// mono() [0x4d154f] | ||
121 | /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60] | ||
122 | /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a] | ||
123 | /// | ||
124 | /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option | ||
125 | /// causes OpenSimulator to immediately crash with a native stack trace similar to | ||
126 | /// | ||
127 | /// mono() [0x489171] | ||
128 | /// mono() [0x4d154f] | ||
129 | /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60] | ||
130 | /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82] | ||
131 | /// </remarks> | ||
132 | internal static Object UniversalColliderSyncObject = new Object(); | ||
133 | |||
108 | private Random fluidRandomizer = new Random(Environment.TickCount); | 134 | private Random fluidRandomizer = new Random(Environment.TickCount); |
109 | 135 | ||
110 | private const uint m_regionWidth = Constants.RegionSize; | 136 | private const uint m_regionWidth = Constants.RegionSize; |
@@ -799,7 +825,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
799 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) | 825 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) |
800 | return; | 826 | return; |
801 | 827 | ||
802 | count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); | 828 | lock (OdeScene.UniversalColliderSyncObject) |
829 | count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); | ||
830 | |||
803 | if (count > contacts.Length) | 831 | if (count > contacts.Length) |
804 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); | 832 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); |
805 | } | 833 | } |