Add a stack trace to the error output on the recursive read lock warning on my RWlocks. Whilst recursive locks are safe, coupled with other issues we're experiencing with the TaskInventoryDictionary it implies that somewhere the lock is not being freed possibly due to a merge error somewhere, and thus it needs to be looked into.
parent
7fead01786
commit
1ead2ed5ee
|
@ -30,6 +30,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Xml.Schema;
|
using System.Xml.Schema;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -90,6 +91,19 @@ namespace OpenSim.Framework
|
||||||
if (m_itemLock.RecursiveReadCount > 0)
|
if (m_itemLock.RecursiveReadCount > 0)
|
||||||
{
|
{
|
||||||
m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||||
|
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||||
|
|
||||||
|
// write call stack method names
|
||||||
|
foreach (StackFrame stackFrame in stackFrames)
|
||||||
|
{
|
||||||
|
m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{}
|
||||||
m_itemLock.ExitReadLock();
|
m_itemLock.ExitReadLock();
|
||||||
}
|
}
|
||||||
if (m_itemLock.RecursiveWriteCount > 0)
|
if (m_itemLock.RecursiveWriteCount > 0)
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
@ -138,6 +139,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
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_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.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||||
|
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||||
|
|
||||||
|
// write call stack method names
|
||||||
|
foreach (StackFrame stackFrame in stackFrames)
|
||||||
|
{
|
||||||
|
m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name
|
||||||
|
}
|
||||||
|
|
||||||
m_partsLock.ExitReadLock();
|
m_partsLock.ExitReadLock();
|
||||||
}
|
}
|
||||||
catch { } // Ignore errors, to allow resync
|
catch { } // Ignore errors, to allow resync
|
||||||
|
@ -317,7 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
private bool m_scriptListens_notAtTarget = false;
|
private bool m_scriptListens_notAtTarget = false;
|
||||||
|
|
||||||
private bool m_scriptListens_atRotTarget = false;
|
private bool m_scriptListens_atRotTarget = false;
|
||||||
private bool m_scriptListens_notAtRotTarget = false;
|
private bool m_scriptListens_notAtRotTarget = false;
|
||||||
public bool m_dupeInProgress = false;
|
public bool m_dupeInProgress = false;
|
||||||
internal Dictionary<UUID, string> m_savedScriptState = null;
|
internal Dictionary<UUID, string> m_savedScriptState = null;
|
||||||
|
|
||||||
|
@ -475,21 +485,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
part.IgnoreUndoUpdate = false;
|
part.IgnoreUndoUpdate = false;
|
||||||
part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
|
part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
|
||||||
part.GroupPosition = val;
|
part.GroupPosition = val;
|
||||||
if (!m_dupeInProgress)
|
if (!m_dupeInProgress)
|
||||||
{
|
{
|
||||||
part.TriggerScriptChangedEvent(Changed.POSITION);
|
part.TriggerScriptChangedEvent(Changed.POSITION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_dupeInProgress)
|
||||||
|
{
|
||||||
|
foreach (ScenePresence av in m_linkedAvatars)
|
||||||
|
{
|
||||||
|
Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
|
||||||
|
av.AbsolutePosition += offset;
|
||||||
|
av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
|
||||||
|
av.SendFullUpdateToAllClients();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!m_dupeInProgress)
|
|
||||||
{
|
|
||||||
foreach (ScenePresence av in m_linkedAvatars)
|
|
||||||
{
|
|
||||||
Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
|
|
||||||
av.AbsolutePosition += offset;
|
|
||||||
av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
|
|
||||||
av.SendFullUpdateToAllClients();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (m_rootPart.PhysActor != null)
|
//if (m_rootPart.PhysActor != null)
|
||||||
|
@ -1805,95 +1815,95 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
|
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public SceneObjectGroup Copy(bool userExposed)
|
public SceneObjectGroup Copy(bool userExposed)
|
||||||
{
|
{
|
||||||
SceneObjectGroup dupe;
|
SceneObjectGroup dupe;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_dupeInProgress = true;
|
m_dupeInProgress = true;
|
||||||
dupe = (SceneObjectGroup)MemberwiseClone();
|
dupe = (SceneObjectGroup)MemberwiseClone();
|
||||||
dupe.m_isBackedUp = false;
|
dupe.m_isBackedUp = false;
|
||||||
dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
|
dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
|
||||||
// Warning, The following code related to previousAttachmentStatus is needed so that clones of
|
// Warning, The following code related to previousAttachmentStatus is needed so that clones of
|
||||||
// attachments do not bordercross while they're being duplicated. This is hacktastic!
|
// attachments do not bordercross while they're being duplicated. This is hacktastic!
|
||||||
// Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
|
// Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
|
||||||
// unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
|
// unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
|
||||||
// (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
|
// (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
|
||||||
// then restore it's attachment state
|
// then restore it's attachment state
|
||||||
|
|
||||||
// This is only necessary when userExposed is false!
|
// This is only necessary when userExposed is false!
|
||||||
|
|
||||||
bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
|
bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
|
||||||
|
|
||||||
if (!userExposed)
|
if (!userExposed)
|
||||||
dupe.RootPart.IsAttachment = true;
|
dupe.RootPart.IsAttachment = true;
|
||||||
|
|
||||||
dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
|
dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
|
||||||
|
|
||||||
if (!userExposed)
|
if (!userExposed)
|
||||||
{
|
{
|
||||||
dupe.RootPart.IsAttachment = previousAttachmentStatus;
|
dupe.RootPart.IsAttachment = previousAttachmentStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
|
dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
|
||||||
dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
|
dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
|
||||||
|
|
||||||
if (userExposed)
|
if (userExposed)
|
||||||
dupe.m_rootPart.TrimPermissions();
|
dupe.m_rootPart.TrimPermissions();
|
||||||
|
|
||||||
/// may need to create a new Physics actor.
|
/// may need to create a new Physics actor.
|
||||||
if (dupe.RootPart.PhysActor != null && userExposed)
|
if (dupe.RootPart.PhysActor != null && userExposed)
|
||||||
{
|
{
|
||||||
PrimitiveBaseShape pbs = dupe.RootPart.Shape;
|
PrimitiveBaseShape pbs = dupe.RootPart.Shape;
|
||||||
|
|
||||||
dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
|
dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
|
||||||
dupe.RootPart.Name,
|
dupe.RootPart.Name,
|
||||||
pbs,
|
pbs,
|
||||||
dupe.RootPart.AbsolutePosition,
|
dupe.RootPart.AbsolutePosition,
|
||||||
dupe.RootPart.Scale,
|
dupe.RootPart.Scale,
|
||||||
dupe.RootPart.RotationOffset,
|
dupe.RootPart.RotationOffset,
|
||||||
dupe.RootPart.PhysActor.IsPhysical);
|
dupe.RootPart.PhysActor.IsPhysical);
|
||||||
|
|
||||||
dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
|
dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
|
||||||
dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
|
dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SceneObjectPart> partList;
|
List<SceneObjectPart> partList;
|
||||||
|
|
||||||
lockPartsForRead(true);
|
lockPartsForRead(true);
|
||||||
|
|
||||||
partList = new List<SceneObjectPart>(m_parts.Values);
|
partList = new List<SceneObjectPart>(m_parts.Values);
|
||||||
|
|
||||||
lockPartsForRead(false);
|
lockPartsForRead(false);
|
||||||
|
|
||||||
partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
|
partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
|
||||||
{
|
{
|
||||||
return p1.LinkNum.CompareTo(p2.LinkNum);
|
return p1.LinkNum.CompareTo(p2.LinkNum);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (SceneObjectPart part in partList)
|
foreach (SceneObjectPart part in partList)
|
||||||
{
|
{
|
||||||
if (part.UUID != m_rootPart.UUID)
|
if (part.UUID != m_rootPart.UUID)
|
||||||
{
|
{
|
||||||
SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
|
SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
|
||||||
|
|
||||||
newPart.LinkNum = part.LinkNum;
|
newPart.LinkNum = part.LinkNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userExposed)
|
if (userExposed)
|
||||||
{
|
{
|
||||||
dupe.UpdateParentIDs();
|
dupe.UpdateParentIDs();
|
||||||
dupe.HasGroupChanged = true;
|
dupe.HasGroupChanged = true;
|
||||||
dupe.AttachToBackup();
|
dupe.AttachToBackup();
|
||||||
|
|
||||||
ScheduleGroupForFullUpdate();
|
ScheduleGroupForFullUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
m_dupeInProgress = false;
|
m_dupeInProgress = false;
|
||||||
}
|
}
|
||||||
return dupe;
|
return dupe;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue