When attachments are being saved and deleted for a closing root agent, delete first to avoid a hud race condition with update threads.

If delete doesn't occur first then the update thread can outrace the IsAttachment = false necessary to save attachments and send hud artifacts to other viewers.
0.7.3-extended
Justin Clark-Casey (justincc) 2012-06-25 22:48:13 +01:00
parent 0ac040d9ca
commit 8dedd91961
4 changed files with 42 additions and 29 deletions

View File

@ -152,31 +152,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
} }
} }
public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted) public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted)
{ {
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
if (!Enabled) if (!Enabled)
return; return;
foreach (SceneObjectGroup grp in sp.GetAttachments()) // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
lock (sp.AttachmentsSyncLock)
{ {
grp.IsAttachment = false; foreach (SceneObjectGroup grp in sp.GetAttachments())
grp.AbsolutePosition = grp.RootPart.AttachedPos; {
UpdateKnownItem(sp, grp, saveAllScripted); grp.Scene.DeleteSceneObject(grp, false);
grp.IsAttachment = true;
if (saveChanged || saveAllScripted)
{
grp.IsAttachment = false;
grp.AbsolutePosition = grp.RootPart.AttachedPos;
UpdateKnownItem(sp, grp, saveAllScripted);
}
}
sp.ClearAttachments();
} }
} }
public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
{ {
if (!Enabled)
return;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", // "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
// m_scene.RegionInfo.RegionName, sp.Name, silent); // m_scene.RegionInfo.RegionName, sp.Name, silent);
if (!Enabled)
return;
foreach (SceneObjectGroup sop in sp.GetAttachments()) foreach (SceneObjectGroup sop in sp.GetAttachments())
{ {
sop.Scene.DeleteSceneObject(sop, silent); sop.Scene.DeleteSceneObject(sop, silent);

View File

@ -43,10 +43,15 @@ namespace OpenSim.Region.Framework.Interfaces
void RezAttachments(IScenePresence sp); void RezAttachments(IScenePresence sp);
/// <summary> /// <summary>
/// Save the attachments that have change on this presence. /// Derez the attachements for a scene presence that is closing.
/// </summary> /// </summary>
/// <param name="sp"></param> /// <remarks>
void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted); /// Attachment changes are saved.
/// </remarks>
/// <param name="sp">The presence closing</param>
/// <param name="saveChanged">Save changed attachments.</param>
/// <param name="saveAllScripted">Save attachments with scripts even if they haven't changed.</para>
void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted);
/// <summary> /// <summary>
/// Delete all the presence's attachments from the scene /// Delete all the presence's attachments from the scene

View File

@ -499,6 +499,7 @@ namespace OpenSim.Region.Framework.Scenes
public IAttachmentsModule AttachmentsModule { get; set; } public IAttachmentsModule AttachmentsModule { get; set; }
public IEntityTransferModule EntityTransferModule { get; private set; } public IEntityTransferModule EntityTransferModule { get; private set; }
public IAgentAssetTransactions AgentTransactionsModule { get; private set; } public IAgentAssetTransactions AgentTransactionsModule { get; private set; }
public IUserManagement UserManagementModule { get; private set; }
public IAvatarFactoryModule AvatarFactory public IAvatarFactoryModule AvatarFactory
{ {
@ -1222,6 +1223,7 @@ namespace OpenSim.Region.Framework.Scenes
EntityTransferModule = RequestModuleInterface<IEntityTransferModule>(); EntityTransferModule = RequestModuleInterface<IEntityTransferModule>();
m_groupsModule = RequestModuleInterface<IGroupsModule>(); m_groupsModule = RequestModuleInterface<IGroupsModule>();
AgentTransactionsModule = RequestModuleInterface<IAgentAssetTransactions>(); AgentTransactionsModule = RequestModuleInterface<IAgentAssetTransactions>();
UserManagementModule = RequestModuleInterface<IUserManagement>();
} }
#endregion #endregion
@ -1994,9 +1996,8 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.SetGroup(groupID, null); sceneObject.SetGroup(groupID, null);
} }
IUserManagement uman = RequestModuleInterface<IUserManagement>(); if (UserManagementModule != null)
if (uman != null) sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID);
sceneObject.RootPart.CreatorIdentification = uman.GetUserUUI(ownerID);
sceneObject.ScheduleGroupForFullUpdate(); sceneObject.ScheduleGroupForFullUpdate();
@ -2692,14 +2693,13 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="aCircuit"></param> /// <param name="aCircuit"></param>
private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit)
{ {
IUserManagement uMan = RequestModuleInterface<IUserManagement>(); if (UserManagementModule != null)
if (uMan != null)
{ {
string first = aCircuit.firstname, last = aCircuit.lastname; string first = aCircuit.firstname, last = aCircuit.lastname;
if (sp.PresenceType == PresenceType.Npc) if (sp.PresenceType == PresenceType.Npc)
{ {
uMan.AddUser(aCircuit.AgentID, first, last); UserManagementModule.AddUser(aCircuit.AgentID, first, last);
} }
else else
{ {
@ -2718,7 +2718,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
uMan.AddUser(aCircuit.AgentID, first, last, homeURL); UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL);
} }
} }
} }
@ -3275,17 +3275,19 @@ namespace OpenSim.Region.Framework.Scenes
if (!isChildAgent) if (!isChildAgent)
{ {
if (AttachmentsModule != null && avatar.PresenceType != PresenceType.Npc) if (AttachmentsModule != null)
{ {
IUserManagement uMan = RequestModuleInterface<IUserManagement>();
// Don't save attachments for HG visitors, it // Don't save attachments for HG visitors, it
// messes up their inventory. When a HG visitor logs // messes up their inventory. When a HG visitor logs
// out on a foreign grid, their attachments will be // out on a foreign grid, their attachments will be
// reloaded in the state they were in when they left // reloaded in the state they were in when they left
// the home grid. This is best anyway as the visited // the home grid. This is best anyway as the visited
// grid may use an incompatible script engine. // grid may use an incompatible script engine.
if (uMan == null || uMan.IsLocalGridUser(avatar.UUID)) bool saveChanged
AttachmentsModule.SaveChangedAttachments(avatar, false); = avatar.PresenceType != PresenceType.Npc
&& (UserManagementModule == null || UserManagementModule.IsLocalGridUser(avatar.UUID));
AttachmentsModule.DeRezAttachments(avatar, saveChanged, false);
} }
ForEachClient( ForEachClient(

View File

@ -3437,9 +3437,6 @@ namespace OpenSim.Region.Framework.Scenes
public void Close() public void Close()
{ {
if (!IsChildAgent && m_scene.AttachmentsModule != null)
m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
// Clear known regions // Clear known regions
KnownRegions = new Dictionary<ulong, string>(); KnownRegions = new Dictionary<ulong, string>();