Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim.

avinationmerge
CasperW 2009-11-27 18:29:03 +01:00
parent 8bbb88ea4e
commit 9888f95068
3 changed files with 541 additions and 305 deletions

View File

@ -98,6 +98,66 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_hasGroupChanged = false; private bool m_hasGroupChanged = false;
private long timeFirstChanged; private long timeFirstChanged;
private long timeLastChanged; private long timeLastChanged;
private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
public void lockPartsForRead(bool locked)
{
if (locked)
{
if (m_partsLock.RecursiveReadCount > 0)
{
m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
m_partsLock.ExitReadLock();
}
if (m_partsLock.RecursiveWriteCount > 0)
{
m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
m_partsLock.ExitWriteLock();
}
while (!m_partsLock.TryEnterReadLock(60000))
{
m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
if (m_partsLock.IsWriteLockHeld)
{
m_partsLock = new System.Threading.ReaderWriterLockSlim();
}
}
}
else
{
m_partsLock.ExitReadLock();
}
}
public void lockPartsForWrite(bool locked)
{
if (locked)
{
if (m_partsLock.RecursiveReadCount > 0)
{
m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
m_partsLock.ExitReadLock();
}
if (m_partsLock.RecursiveWriteCount > 0)
{
m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
m_partsLock.ExitWriteLock();
}
while (!m_partsLock.TryEnterWriteLock(60000))
{
m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
if (m_partsLock.IsWriteLockHeld)
{
m_partsLock = new System.Threading.ReaderWriterLockSlim();
}
}
}
else
{
m_partsLock.ExitWriteLock();
}
}
public bool HasGroupChanged public bool HasGroupChanged
{ {
@ -243,13 +303,16 @@ namespace OpenSim.Region.Framework.Scenes
set set
{ {
m_regionHandle = value; m_regionHandle = value;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.RegionHandle = m_regionHandle; part.RegionHandle = m_regionHandle;
} }
} }
lockPartsForRead(false);
} }
} }
@ -275,13 +338,16 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.CrossPrimGroupIntoNewRegion(val, this, true); m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
} }
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.GroupPosition = val; part.GroupPosition = val;
} }
} }
lockPartsForRead(false);
//if (m_rootPart.PhysActor != null) //if (m_rootPart.PhysActor != null)
//{ //{
@ -432,13 +498,16 @@ namespace OpenSim.Region.Framework.Scenes
public void SetFromItemID(UUID AssetId) public void SetFromItemID(UUID AssetId)
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.FromItemID = AssetId; part.FromItemID = AssetId;
} }
} }
lockPartsForRead(false);
} }
public UUID GetFromItemID() public UUID GetFromItemID()
@ -505,10 +574,11 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 maxScale = Vector3.Zero; Vector3 maxScale = Vector3.Zero;
Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
Vector3 partscale = part.Scale; Vector3 partscale = part.Scale;
Vector3 partoffset = part.OffsetPosition; Vector3 partoffset = part.OffsetPosition;
@ -519,8 +589,11 @@ namespace OpenSim.Region.Framework.Scenes
maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
} }
} }
lockPartsForRead(false);
finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@ -536,10 +609,11 @@ namespace OpenSim.Region.Framework.Scenes
EntityIntersection result = new EntityIntersection(); EntityIntersection result = new EntityIntersection();
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
// Temporary commented to stop compiler warning // Temporary commented to stop compiler warning
//Vector3 partPosition = //Vector3 partPosition =
// new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@ -567,8 +641,10 @@ namespace OpenSim.Region.Framework.Scenes
result.distance = inter.distance; result.distance = inter.distance;
} }
} }
} }
} }
lockPartsForRead(false);
return result; return result;
} }
@ -581,10 +657,11 @@ namespace OpenSim.Region.Framework.Scenes
public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
{ {
float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
Vector3 worldPos = part.GetWorldPosition(); Vector3 worldPos = part.GetWorldPosition();
Vector3 offset = worldPos - AbsolutePosition; Vector3 offset = worldPos - AbsolutePosition;
Quaternion worldRot; Quaternion worldRot;
@ -643,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes
backBottomRight.Y = orig.Y + (part.Scale.Y / 2); backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
backBottomRight.Z = orig.Z - (part.Scale.Z / 2); backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
//m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
//m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
//m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@ -814,6 +893,7 @@ namespace OpenSim.Region.Framework.Scenes
minZ = backBottomLeft.Z; minZ = backBottomLeft.Z;
} }
} }
lockPartsForRead(false);
Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
@ -842,17 +922,20 @@ namespace OpenSim.Region.Framework.Scenes
Dictionary<UUID,string> states = new Dictionary<UUID,string>(); Dictionary<UUID,string> states = new Dictionary<UUID,string>();
// Capture script state while holding the lock // Capture script state while holding the lock
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
foreach (UUID itemid in pstates.Keys) foreach (UUID itemid in pstates.Keys)
{ {
states.Add(itemid, pstates[itemid]); states.Add(itemid, pstates[itemid]);
} }
} }
} }
lockPartsForRead(false);
if (states.Count > 0) if (states.Count > 0)
{ {
@ -1014,13 +1097,16 @@ namespace OpenSim.Region.Framework.Scenes
public override void UpdateMovement() public override void UpdateMovement()
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.UpdateMovement(); part.UpdateMovement();
} }
} }
lockPartsForRead(false);
} }
public ushort GetTimeDilation() public ushort GetTimeDilation()
@ -1064,7 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="part"></param> /// <param name="part"></param>
public void AddPart(SceneObjectPart part) public void AddPart(SceneObjectPart part)
{ {
lock (m_parts) lockPartsForWrite(true);
{ {
part.SetParent(this); part.SetParent(this);
m_parts.Add(part.UUID, part); m_parts.Add(part.UUID, part);
@ -1074,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes
if (part.LinkNum == 2 && RootPart != null) if (part.LinkNum == 2 && RootPart != null)
RootPart.LinkNum = 1; RootPart.LinkNum = 1;
} }
lockPartsForWrite(false);
} }
/// <summary> /// <summary>
@ -1081,28 +1168,33 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
private void UpdateParentIDs() private void UpdateParentIDs()
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part.UUID != m_rootPart.UUID) if (part.UUID != m_rootPart.UUID)
{ {
part.ParentID = m_rootPart.LocalId; part.ParentID = m_rootPart.LocalId;
} }
} }
} }
lockPartsForRead(false);
} }
public void RegenerateFullIDs() public void RegenerateFullIDs()
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.UUID = UUID.Random(); part.UUID = UUID.Random();
} }
} }
lockPartsForRead(false);
} }
// helper provided for parts. // helper provided for parts.
@ -1183,29 +1275,33 @@ namespace OpenSim.Region.Framework.Scenes
DetachFromBackup(); DetachFromBackup();
lock (m_parts) lockPartsForRead(true);
List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
lockPartsForRead(false);
foreach (SceneObjectPart part in values)
{ {
foreach (SceneObjectPart part in m_parts.Values)
{
// part.Inventory.RemoveScriptInstances(); // part.Inventory.RemoveScriptInstances();
ScenePresence[] avatars = Scene.GetScenePresences(); ScenePresence[] avatars = Scene.GetScenePresences();
for (int i = 0; i < avatars.Length; i++) for (int i = 0; i < avatars.Length; i++)
{
if (avatars[i].ParentID == LocalId)
{ {
if (avatars[i].ParentID == LocalId) avatars[i].StandUp();
{ }
avatars[i].StandUp();
}
if (!silent) if (!silent)
{ {
part.UpdateFlag = 0; part.UpdateFlag = 0;
if (part == m_rootPart) if (part == m_rootPart)
avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
} }
} }
} }
} }
public void AddScriptLPS(int count) public void AddScriptLPS(int count)
@ -1230,17 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes
scriptEvents aggregateScriptEvents=0; scriptEvents aggregateScriptEvents=0;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part == null) if (part == null)
continue; continue;
if (part != RootPart) if (part != RootPart)
part.ObjectFlags = objectflagupdate; part.ObjectFlags = objectflagupdate;
aggregateScriptEvents |= part.AggregateScriptEvents; aggregateScriptEvents |= part.AggregateScriptEvents;
} }
} }
lockPartsForRead(false);
m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@ -1273,42 +1372,52 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="m_physicalPrim"></param> /// <param name="m_physicalPrim"></param>
public void ApplyPhysics(bool m_physicalPrim) public void ApplyPhysics(bool m_physicalPrim)
{ {
lock (m_parts) lockPartsForRead(true);
if (m_parts.Count > 1)
{ {
if (m_parts.Count > 1) List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
lockPartsForRead(false);
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
foreach (SceneObjectPart part in values)
{ {
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
foreach (SceneObjectPart part in m_parts.Values) if (part.LocalId != m_rootPart.LocalId)
{ {
if (part.LocalId != m_rootPart.LocalId) part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
{
part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
}
} }
// Hack to get the physics scene geometries in the right spot
ResetChildPrimPhysicsPositions();
}
else
{
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
} }
// Hack to get the physics scene geometries in the right spot
ResetChildPrimPhysicsPositions();
}
else
{
lockPartsForRead(false);
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
} }
} }
public void SetOwnerId(UUID userId) public void SetOwnerId(UUID userId)
{ {
ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); ForEachPart(delegate(SceneObjectPart part)
{
part.OwnerID = userId;
});
} }
public void ForEachPart(Action<SceneObjectPart> whatToDo) public void ForEachPart(Action<SceneObjectPart> whatToDo)
{ {
lock (m_parts) lockPartsForRead(true);
List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
lockPartsForRead(false);
foreach (SceneObjectPart part in values)
{ {
foreach (SceneObjectPart part in m_parts.Values)
{ whatToDo(part);
whatToDo(part);
}
} }
} }
@ -1407,14 +1516,17 @@ namespace OpenSim.Region.Framework.Scenes
{ {
SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
} }
} }
lockPartsForRead(false);
} }
/// <summary> /// <summary>
@ -1509,10 +1621,11 @@ namespace OpenSim.Region.Framework.Scenes
List<SceneObjectPart> partList; List<SceneObjectPart> partList;
lock (m_parts) lockPartsForRead(true);
{
partList = new List<SceneObjectPart>(m_parts.Values); partList = new List<SceneObjectPart>(m_parts.Values);
}
lockPartsForRead(false);
partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
{ {
@ -1835,10 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
newPart.SetParent(this); newPart.SetParent(this);
lock (m_parts) lockPartsForWrite(true);
{ {
m_parts.Add(newPart.UUID, newPart); m_parts.Add(newPart.UUID, newPart);
} }
lockPartsForWrite(false);
SetPartAsNonRoot(newPart); SetPartAsNonRoot(newPart);
@ -1901,7 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
//if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
// return; // return;
lock (m_parts) lockPartsForRead(true);
{ {
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
@ -1919,34 +2033,43 @@ namespace OpenSim.Region.Framework.Scenes
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.SendScheduledUpdates(); part.SendScheduledUpdates();
} }
} }
lockPartsForRead(false);
} }
public void ScheduleFullUpdateToAvatar(ScenePresence presence) public void ScheduleFullUpdateToAvatar(ScenePresence presence)
{ {
RootPart.AddFullUpdateToAvatar(presence); RootPart.AddFullUpdateToAvatar(presence);
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.AddFullUpdateToAvatar(presence); part.AddFullUpdateToAvatar(presence);
} }
} }
lockPartsForRead(false);
} }
public void ScheduleTerseUpdateToAvatar(ScenePresence presence) public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.AddTerseUpdateToAvatar(presence); part.AddTerseUpdateToAvatar(presence);
} }
} }
lockPartsForRead(false);
} }
/// <summary> /// <summary>
@ -1957,14 +2080,17 @@ namespace OpenSim.Region.Framework.Scenes
checkAtTargets(); checkAtTargets();
RootPart.ScheduleFullUpdate(); RootPart.ScheduleFullUpdate();
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.ScheduleFullUpdate(); part.ScheduleFullUpdate();
} }
} }
lockPartsForRead(false);
} }
/// <summary> /// <summary>
@ -1972,13 +2098,16 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void ScheduleGroupForTerseUpdate() public void ScheduleGroupForTerseUpdate()
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.ScheduleTerseUpdate(); part.ScheduleTerseUpdate();
} }
} }
lockPartsForRead(false);
} }
/// <summary> /// <summary>
@ -1991,14 +2120,17 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.SendFullUpdateToAllClients(); RootPart.SendFullUpdateToAllClients();
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.SendFullUpdateToAllClients(); part.SendFullUpdateToAllClients();
} }
} }
lockPartsForRead(false);
} }
/// <summary> /// <summary>
@ -2029,14 +2161,15 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (IsDeleted) if (IsDeleted)
return; return;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.SendTerseUpdateToAllClients(); part.SendTerseUpdateToAllClients();
} }
} }
lockPartsForRead(false);
} }
#endregion #endregion
@ -2050,16 +2183,18 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>null if no child part with that linknum or child part</returns> /// <returns>null if no child part with that linknum or child part</returns>
public SceneObjectPart GetLinkNumPart(int linknum) public SceneObjectPart GetLinkNumPart(int linknum)
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part.LinkNum == linknum) if (part.LinkNum == linknum)
{ {
lockPartsForRead(false);
return part; return part;
} }
} }
} }
lockPartsForRead(false);
return null; return null;
} }
@ -2087,17 +2222,19 @@ namespace OpenSim.Region.Framework.Scenes
public SceneObjectPart GetChildPart(uint localID) public SceneObjectPart GetChildPart(uint localID)
{ {
//m_log.DebugFormat("Entered looking for {0}", localID); //m_log.DebugFormat("Entered looking for {0}", localID);
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
//m_log.DebugFormat("Found {0}", part.LocalId); //m_log.DebugFormat("Found {0}", part.LocalId);
if (part.LocalId == localID) if (part.LocalId == localID)
{ {
lockPartsForRead(false);
return part; return part;
} }
} }
} }
lockPartsForRead(false);
return null; return null;
} }
@ -2127,17 +2264,19 @@ namespace OpenSim.Region.Framework.Scenes
public bool HasChildPrim(uint localID) public bool HasChildPrim(uint localID)
{ {
//m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
//m_log.DebugFormat("Found {0}", part.LocalId); //m_log.DebugFormat("Found {0}", part.LocalId);
if (part.LocalId == localID) if (part.LocalId == localID)
{ {
lockPartsForRead(false);
return true; return true;
} }
} }
} }
lockPartsForRead(false);
return false; return false;
} }
@ -2187,53 +2326,57 @@ namespace OpenSim.Region.Framework.Scenes
if (m_rootPart.LinkNum == 0) if (m_rootPart.LinkNum == 0)
m_rootPart.LinkNum = 1; m_rootPart.LinkNum = 1;
lock (m_parts) lockPartsForWrite(true);
m_parts.Add(linkPart.UUID, linkPart);
lockPartsForWrite(false);
// Insert in terms of link numbers, the new links
// before the current ones (with the exception of
// the root prim. Shuffle the old ones up
lockPartsForRead(true);
foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
{ {
m_parts.Add(linkPart.UUID, linkPart); if (kvp.Value.LinkNum != 1)
// Insert in terms of link numbers, the new links
// before the current ones (with the exception of
// the root prim. Shuffle the old ones up
foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
{ {
if (kvp.Value.LinkNum != 1) // Don't update root prim link number
{ kvp.Value.LinkNum += objectGroup.PrimCount;
// Don't update root prim link number
kvp.Value.LinkNum += objectGroup.PrimCount;
}
} }
}
lockPartsForRead(false);
linkPart.LinkNum = 2; linkPart.LinkNum = 2;
linkPart.SetParent(this); linkPart.SetParent(this);
linkPart.AddFlag(PrimFlags.CreateSelected); linkPart.AddFlag(PrimFlags.CreateSelected);
//if (linkPart.PhysActor != null) //if (linkPart.PhysActor != null)
//{ //{
// m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
//linkPart.PhysActor = null; //linkPart.PhysActor = null;
//} //}
//TODO: rest of parts //TODO: rest of parts
int linkNum = 3; int linkNum = 3;
foreach (SceneObjectPart part in objectGroup.Children.Values) foreach (SceneObjectPart part in objectGroup.Children.Values)
{
if (part.UUID != objectGroup.m_rootPart.UUID)
{ {
if (part.UUID != objectGroup.m_rootPart.UUID) LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
{
LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
}
part.ClearUndoState();
} }
part.ClearUndoState();
} }
m_scene.UnlinkSceneObject(objectGroup.UUID, true); m_scene.UnlinkSceneObject(objectGroup.UUID, true);
objectGroup.m_isDeleted = true; objectGroup.m_isDeleted = true;
objectGroup.lockPartsForWrite(true);
lock (objectGroup.m_parts) objectGroup.m_parts.Clear();
{
objectGroup.m_parts.Clear(); objectGroup.lockPartsForWrite(false);
}
// Can't do this yet since backup still makes use of the root part without any synchronization // Can't do this yet since backup still makes use of the root part without any synchronization
// objectGroup.m_rootPart = null; // objectGroup.m_rootPart = null;
@ -2292,11 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion worldRot = linkPart.GetWorldRotation(); Quaternion worldRot = linkPart.GetWorldRotation();
// Remove the part from this object // Remove the part from this object
lock (m_parts) lockPartsForWrite(true);
{ {
m_parts.Remove(linkPart.UUID); m_parts.Remove(linkPart.UUID);
} }
lockPartsForWrite(false);
lockPartsForRead(true);
if (m_parts.Count == 1 && RootPart != null) //Single prim is left if (m_parts.Count == 1 && RootPart != null) //Single prim is left
RootPart.LinkNum = 0; RootPart.LinkNum = 0;
else else
@ -2307,6 +2451,7 @@ namespace OpenSim.Region.Framework.Scenes
p.LinkNum--; p.LinkNum--;
} }
} }
lockPartsForRead(false);
linkPart.ParentID = 0; linkPart.ParentID = 0;
linkPart.LinkNum = 0; linkPart.LinkNum = 0;
@ -2624,22 +2769,23 @@ namespace OpenSim.Region.Framework.Scenes
if (selectionPart != null) if (selectionPart != null)
{ {
lock (m_parts) lockPartsForRead(true);
List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
lockPartsForRead(false);
foreach (SceneObjectPart part in parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
{ {
if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) UsePhysics = false; // Reset physics
{ break;
UsePhysics = false; // Reset physics
break;
}
}
foreach (SceneObjectPart part in m_parts.Values)
{
part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
} }
} }
foreach (SceneObjectPart part in parts)
{
part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
}
} }
} }
@ -2863,7 +3009,7 @@ namespace OpenSim.Region.Framework.Scenes
prevScale.Z *= z; prevScale.Z *= z;
part.Resize(prevScale); part.Resize(prevScale);
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart obPart in m_parts.Values) foreach (SceneObjectPart obPart in m_parts.Values)
{ {
@ -2882,6 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
lockPartsForRead(false);
if (part.PhysActor != null) if (part.PhysActor != null)
{ {
@ -2962,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
axDiff *= Quaternion.Inverse(partRotation); axDiff *= Quaternion.Inverse(partRotation);
diff = axDiff; diff = axDiff;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart obPart in m_parts.Values) foreach (SceneObjectPart obPart in m_parts.Values)
{ {
@ -2972,6 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
lockPartsForRead(false);
AbsolutePosition = newPos; AbsolutePosition = newPos;
@ -3089,7 +3237,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
} }
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart prim in m_parts.Values) foreach (SceneObjectPart prim in m_parts.Values)
{ {
@ -3107,6 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
lockPartsForRead(false);
m_rootPart.ScheduleTerseUpdate(); m_rootPart.ScheduleTerseUpdate();
} }
@ -3205,7 +3354,7 @@ namespace OpenSim.Region.Framework.Scenes
if (atTargets.Count > 0) if (atTargets.Count > 0)
{ {
uint[] localids = new uint[0]; uint[] localids = new uint[0];
lock (m_parts) lockPartsForRead(true);
{ {
localids = new uint[m_parts.Count]; localids = new uint[m_parts.Count];
int cntr = 0; int cntr = 0;
@ -3215,6 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes
cntr++; cntr++;
} }
} }
lockPartsForRead(false);
for (int ctr = 0; ctr < localids.Length; ctr++) for (int ctr = 0; ctr < localids.Length; ctr++)
{ {
@ -3233,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
//trigger not_at_target //trigger not_at_target
uint[] localids = new uint[0]; uint[] localids = new uint[0];
lock (m_parts) lockPartsForRead(true);
{ {
localids = new uint[m_parts.Count]; localids = new uint[m_parts.Count];
int cntr = 0; int cntr = 0;
@ -3243,7 +3393,8 @@ namespace OpenSim.Region.Framework.Scenes
cntr++; cntr++;
} }
} }
lockPartsForRead(false);
for (int ctr = 0; ctr < localids.Length; ctr++) for (int ctr = 0; ctr < localids.Length; ctr++)
{ {
m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@ -3256,19 +3407,20 @@ namespace OpenSim.Region.Framework.Scenes
public float GetMass() public float GetMass()
{ {
float retmass = 0f; float retmass = 0f;
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
retmass += part.GetMass(); retmass += part.GetMass();
} }
} }
lockPartsForRead(false);
return retmass; return retmass;
} }
public void CheckSculptAndLoad() public void CheckSculptAndLoad()
{ {
lock (m_parts) lockPartsForRead(true);
{ {
if (!IsDeleted) if (!IsDeleted)
{ {
@ -3293,6 +3445,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
lockPartsForRead(false);
} }
protected void AssetReceived(string id, Object sender, AssetBase asset) protected void AssetReceived(string id, Object sender, AssetBase asset)
@ -3313,7 +3466,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="client"></param> /// <param name="client"></param>
public void SetGroup(UUID GroupID, IClientAPI client) public void SetGroup(UUID GroupID, IClientAPI client)
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
@ -3323,7 +3476,7 @@ namespace OpenSim.Region.Framework.Scenes
HasGroupChanged = true; HasGroupChanged = true;
} }
lockPartsForRead(false);
ScheduleGroupForFullUpdate(); ScheduleGroupForFullUpdate();
} }
@ -3342,11 +3495,12 @@ namespace OpenSim.Region.Framework.Scenes
public void SetAttachmentPoint(byte point) public void SetAttachmentPoint(byte point)
{ {
lock (m_parts) lockPartsForRead(true);
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
part.SetAttachmentPoint(point); part.SetAttachmentPoint(point);
} }
lockPartsForRead(false);
} }
#region ISceneObject #region ISceneObject

View File

@ -2950,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return m_host.OwnerID.ToString(); return m_host.OwnerID.ToString();
} }
[DebuggerNonUserCode]
public void llInstantMessage(string user, string message) public void llInstantMessage(string user, string message)
{ {
UUID result;
if (!UUID.TryParse(user, out result))
{
throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
return;
}
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// We may be able to use ClientView.SendInstantMessage here, but we need a client instance. // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@ -2966,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID friendTransactionID = UUID.Random(); UUID friendTransactionID = UUID.Random();
//m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
GridInstantMessage msg = new GridInstantMessage(); GridInstantMessage msg = new GridInstantMessage();
msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
msg.toAgentID = new Guid(user); // toAgentID.Guid; msg.toAgentID = new Guid(user); // toAgentID.Guid;

View File

@ -101,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private Dictionary<UUID, IScriptInstance> m_Scripts = private Dictionary<UUID, IScriptInstance> m_Scripts =
new Dictionary<UUID, IScriptInstance>(); new Dictionary<UUID, IScriptInstance>();
private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
// Maps the asset ID to the assembly // Maps the asset ID to the assembly
private Dictionary<UUID, string> m_Assemblies = private Dictionary<UUID, string> m_Assemblies =
@ -122,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
IWorkItemResult m_CurrentCompile = null; IWorkItemResult m_CurrentCompile = null;
private void lockScriptsForRead(bool locked)
{
if (locked)
{
if (m_scriptsLock.RecursiveReadCount > 0)
{
m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
m_scriptsLock.ExitReadLock();
}
if (m_scriptsLock.RecursiveWriteCount > 0)
{
m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
m_scriptsLock.ExitWriteLock();
}
while (!m_scriptsLock.TryEnterReadLock(60000))
{
m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
if (m_scriptsLock.IsWriteLockHeld)
{
m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
}
}
}
else
{
m_scriptsLock.ExitReadLock();
}
}
private void lockScriptsForWrite(bool locked)
{
if (locked)
{
if (m_scriptsLock.RecursiveReadCount > 0)
{
m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
m_scriptsLock.ExitReadLock();
}
if (m_scriptsLock.RecursiveWriteCount > 0)
{
m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
m_scriptsLock.ExitWriteLock();
}
while (!m_scriptsLock.TryEnterWriteLock(60000))
{
m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
if (m_scriptsLock.IsWriteLockHeld)
{
m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
}
}
}
else
{
m_scriptsLock.ExitWriteLock();
}
}
public string ScriptEngineName public string ScriptEngineName
{ {
get { return "XEngine"; } get { return "XEngine"; }
@ -261,43 +322,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
lock (m_Scripts) lockScriptsForRead(true);
foreach (IScriptInstance instance in m_Scripts.Values)
{ {
foreach (IScriptInstance instance in m_Scripts.Values) // Force a final state save
//
if (m_Assemblies.ContainsKey(instance.AssetID))
{ {
// Force a final state save string assembly = m_Assemblies[instance.AssetID];
// instance.SaveState(assembly);
if (m_Assemblies.ContainsKey(instance.AssetID)) }
{
string assembly = m_Assemblies[instance.AssetID]; // Clear the event queue and abort the instance thread
instance.SaveState(assembly); //
} instance.ClearQueue();
instance.Stop(0);
// Clear the event queue and abort the instance thread
// // Release events, timer, etc
instance.ClearQueue(); //
instance.Stop(0); instance.DestroyScriptInstance();
// Release events, timer, etc // Unload scripts and app domains
// // Must be done explicitly because they have infinite
instance.DestroyScriptInstance(); // lifetime
//
// Unload scripts and app domains m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
// Must be done explicitly because they have infinite if (m_DomainScripts[instance.AppDomain].Count == 0)
// lifetime {
// m_DomainScripts.Remove(instance.AppDomain);
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); UnloadAppDomain(instance.AppDomain);
if (m_DomainScripts[instance.AppDomain].Count == 0)
{
m_DomainScripts.Remove(instance.AppDomain);
UnloadAppDomain(instance.AppDomain);
}
} }
m_Scripts.Clear();
m_PrimObjects.Clear();
m_Assemblies.Clear();
m_DomainScripts.Clear();
} }
lockScriptsForRead(false);
lockScriptsForWrite(true);
m_Scripts.Clear();
lockScriptsForWrite(false);
m_PrimObjects.Clear();
m_Assemblies.Clear();
m_DomainScripts.Clear();
lock (m_ScriptEngines) lock (m_ScriptEngines)
{ {
m_ScriptEngines.Remove(this); m_ScriptEngines.Remove(this);
@ -356,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
List<IScriptInstance> instances = new List<IScriptInstance>(); List<IScriptInstance> instances = new List<IScriptInstance>();
lock (m_Scripts) lockScriptsForRead(true);
{ foreach (IScriptInstance instance in m_Scripts.Values)
foreach (IScriptInstance instance in m_Scripts.Values)
instances.Add(instance); instances.Add(instance);
} lockScriptsForRead(false);
foreach (IScriptInstance i in instances) foreach (IScriptInstance i in instances)
{ {
string assembly = String.Empty; string assembly = String.Empty;
lock (m_Scripts)
{
if (!m_Assemblies.ContainsKey(i.AssetID)) if (!m_Assemblies.ContainsKey(i.AssetID))
continue; continue;
assembly = m_Assemblies[i.AssetID]; assembly = m_Assemblies[i.AssetID];
}
i.SaveState(assembly); i.SaveState(assembly);
} }
@ -673,173 +734,184 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return false; return false;
} }
lock (m_Scripts)
ScriptInstance instance = null;
// Create the object record
lockScriptsForRead(true);
if ((!m_Scripts.ContainsKey(itemID)) ||
(m_Scripts[itemID].AssetID != assetID))
{ {
ScriptInstance instance = null; lockScriptsForRead(false);
// Create the object record
if ((!m_Scripts.ContainsKey(itemID)) || UUID appDomain = assetID;
(m_Scripts[itemID].AssetID != assetID))
if (part.ParentGroup.IsAttachment)
appDomain = part.ParentGroup.RootPart.UUID;
if (!m_AppDomains.ContainsKey(appDomain))
{ {
UUID appDomain = assetID; try
if (part.ParentGroup.IsAttachment)
appDomain = part.ParentGroup.RootPart.UUID;
if (!m_AppDomains.ContainsKey(appDomain))
{ {
try AppDomainSetup appSetup = new AppDomainSetup();
{ // appSetup.ApplicationBase = Path.Combine(
AppDomainSetup appSetup = new AppDomainSetup(); // "ScriptEngines",
// appSetup.ApplicationBase = Path.Combine( // m_Scene.RegionInfo.RegionID.ToString());
// "ScriptEngines",
// m_Scene.RegionInfo.RegionID.ToString());
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence evidence = new Evidence(baseEvidence); Evidence evidence = new Evidence(baseEvidence);
AppDomain sandbox; AppDomain sandbox;
if (m_AppDomainLoading) if (m_AppDomainLoading)
sandbox = AppDomain.CreateDomain( sandbox = AppDomain.CreateDomain(
m_Scene.RegionInfo.RegionID.ToString(), m_Scene.RegionInfo.RegionID.ToString(),
evidence, appSetup); evidence, appSetup);
else else
sandbox = AppDomain.CurrentDomain; sandbox = AppDomain.CurrentDomain;
//PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
//AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
//PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
//PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
//CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
//sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
//sandbox.SetAppDomainPolicy(sandboxPolicy);
m_AppDomains[appDomain] = sandbox;
m_AppDomains[appDomain].AssemblyResolve += //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
new ResolveEventHandler( //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
AssemblyResolver.OnAssemblyResolve); //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
m_DomainScripts[appDomain] = new List<UUID>(); //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
} //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
catch (Exception e) //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
{ //sandbox.SetAppDomainPolicy(sandboxPolicy);
m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
m_ScriptErrorMessage += "Exception creating app domain:\n"; m_AppDomains[appDomain] = sandbox;
m_ScriptFailCount++;
lock (m_AddingAssemblies) m_AppDomains[appDomain].AssemblyResolve +=
{ new ResolveEventHandler(
m_AddingAssemblies[assembly]--; AssemblyResolver.OnAssemblyResolve);
} m_DomainScripts[appDomain] = new List<UUID>();
return false;
}
} }
m_DomainScripts[appDomain].Add(itemID); catch (Exception e)
instance = new ScriptInstance(this, part,
itemID, assetID, assembly,
m_AppDomains[appDomain],
part.ParentGroup.RootPart.Name,
item.Name, startParam, postOnRez,
stateSource, m_MaxScriptQueue);
m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
if (presence != null)
{ {
ShowScriptSaveResponse(item.OwnerID, m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
assetID, "Compile successful", true); m_ScriptErrorMessage += "Exception creating app domain:\n";
m_ScriptFailCount++;
lock (m_AddingAssemblies)
{
m_AddingAssemblies[assembly]--;
}
return false;
} }
instance.AppDomain = appDomain;
instance.LineMap = linemap;
m_Scripts[itemID] = instance;
} }
m_DomainScripts[appDomain].Add(itemID);
lock (m_PrimObjects) instance = new ScriptInstance(this, part,
itemID, assetID, assembly,
m_AppDomains[appDomain],
part.ParentGroup.RootPart.Name,
item.Name, startParam, postOnRez,
stateSource, m_MaxScriptQueue);
m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
if (presence != null)
{ {
if (!m_PrimObjects.ContainsKey(localID)) ShowScriptSaveResponse(item.OwnerID,
m_PrimObjects[localID] = new List<UUID>(); assetID, "Compile successful", true);
if (!m_PrimObjects[localID].Contains(itemID))
m_PrimObjects[localID].Add(itemID);
} }
if (!m_Assemblies.ContainsKey(assetID)) instance.AppDomain = appDomain;
m_Assemblies[assetID] = assembly; instance.LineMap = linemap;
lockScriptsForWrite(true);
lock (m_AddingAssemblies) m_Scripts[itemID] = instance;
{ lockScriptsForWrite(false);
m_AddingAssemblies[assembly]--;
}
if (instance!=null)
instance.Init();
} }
else
{
lockScriptsForRead(false);
}
lock (m_PrimObjects)
{
if (!m_PrimObjects.ContainsKey(localID))
m_PrimObjects[localID] = new List<UUID>();
if (!m_PrimObjects[localID].Contains(itemID))
m_PrimObjects[localID].Add(itemID);
}
if (!m_Assemblies.ContainsKey(assetID))
m_Assemblies[assetID] = assembly;
lock (m_AddingAssemblies)
{
m_AddingAssemblies[assembly]--;
}
if (instance!=null)
instance.Init();
return true; return true;
} }
public void OnRemoveScript(uint localID, UUID itemID) public void OnRemoveScript(uint localID, UUID itemID)
{ {
lock (m_Scripts) lockScriptsForRead(true);
// Do we even have it?
if (!m_Scripts.ContainsKey(itemID))
{ {
// Do we even have it? lockScriptsForRead(false);
if (!m_Scripts.ContainsKey(itemID)) return;
return; }
IScriptInstance instance=m_Scripts[itemID]; IScriptInstance instance=m_Scripts[itemID];
m_Scripts.Remove(itemID); lockScriptsForRead(false);
lockScriptsForWrite(true);
m_Scripts.Remove(itemID);
lockScriptsForWrite(false);
instance.ClearQueue();
instance.Stop(0);
instance.ClearQueue(); SceneObjectPart part =
instance.Stop(0); m_Scene.GetSceneObjectPart(localID);
SceneObjectPart part = if (part != null)
m_Scene.GetSceneObjectPart(localID); part.RemoveScriptEvents(itemID);
if (part != null)
part.RemoveScriptEvents(itemID);
// bool objectRemoved = false; // bool objectRemoved = false;
lock (m_PrimObjects) lock (m_PrimObjects)
{
// Remove the script from it's prim
if (m_PrimObjects.ContainsKey(localID))
{ {
// Remove the script from it's prim // Remove inventory item record
if (m_PrimObjects.ContainsKey(localID)) if (m_PrimObjects[localID].Contains(itemID))
{ m_PrimObjects[localID].Remove(itemID);
// Remove inventory item record
if (m_PrimObjects[localID].Contains(itemID))
m_PrimObjects[localID].Remove(itemID);
// If there are no more scripts, remove prim // If there are no more scripts, remove prim
if (m_PrimObjects[localID].Count == 0) if (m_PrimObjects[localID].Count == 0)
{ {
m_PrimObjects.Remove(localID); m_PrimObjects.Remove(localID);
// objectRemoved = true; // objectRemoved = true;
}
} }
} }
instance.RemoveState();
instance.DestroyScriptInstance();
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
if (m_DomainScripts[instance.AppDomain].Count == 0)
{
m_DomainScripts.Remove(instance.AppDomain);
UnloadAppDomain(instance.AppDomain);
}
instance = null;
ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
if (handlerObjectRemoved != null)
handlerObjectRemoved(part.UUID);
CleanAssemblies();
} }
instance.RemoveState();
instance.DestroyScriptInstance();
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
if (m_DomainScripts[instance.AppDomain].Count == 0)
{
m_DomainScripts.Remove(instance.AppDomain);
UnloadAppDomain(instance.AppDomain);
}
instance = null;
ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
if (handlerObjectRemoved != null)
handlerObjectRemoved(part.UUID);
CleanAssemblies();
ScriptRemoved handlerScriptRemoved = OnScriptRemoved; ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
if (handlerScriptRemoved != null) if (handlerScriptRemoved != null)
handlerScriptRemoved(itemID); handlerScriptRemoved(itemID);
@ -1091,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private IScriptInstance GetInstance(UUID itemID) private IScriptInstance GetInstance(UUID itemID)
{ {
IScriptInstance instance; IScriptInstance instance;
lock (m_Scripts) lockScriptsForRead(true);
if (!m_Scripts.ContainsKey(itemID))
{ {
if (!m_Scripts.ContainsKey(itemID)) lockScriptsForRead(false);
return null; return null;
instance = m_Scripts[itemID];
} }
instance = m_Scripts[itemID];
lockScriptsForRead(false);
return instance; return instance;
} }
@ -1200,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{ {
List<IScriptInstance> instances = new List<IScriptInstance>(); List<IScriptInstance> instances = new List<IScriptInstance>();
lock (m_Scripts) lockScriptsForRead(true);
{ foreach (IScriptInstance instance in m_Scripts.Values)
foreach (IScriptInstance instance in m_Scripts.Values)
instances.Add(instance); instances.Add(instance);
} lockScriptsForRead(false);
foreach (IScriptInstance i in instances) foreach (IScriptInstance i in instances)
{ {