In AttachmentsModule.DetachSingleAttachmentToInvInternal(), remove attachment before changing properties for correct inventory serialization.

Serialization of attachments requires IsAttachment = false so that correct positions are serialized instead of avatar position.
However, doing this when a hud is still attached allows race conditions with update threads, resulting in hud artifacts on other viewers.
This change sets SOG.IsDeleted before serialization changes take place (IsDeleted itself is not a serialized property).
LLClientView then screens out any deleted SOGs before sending updates to viewers.
0.7.4.1
Justin Clark-Casey (justincc) 2012-06-25 21:08:19 +01:00
parent 6d3ee8bb39
commit 5301648cff
3 changed files with 42 additions and 2 deletions

View File

@ -3808,6 +3808,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
&& part.ParentGroup.HasPrivateAttachmentPoint && part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId) && part.ParentGroup.AttachedAvatar != AgentId)
continue; continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
} }
objectUpdateBlocks.Value.Add(updateBlock); objectUpdateBlocks.Value.Add(updateBlock);
@ -3815,7 +3824,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
else if (!canUseImproved) else if (!canUseImproved)
{ {
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); SceneObjectPart part = (SceneObjectPart)update.Entity;
ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
= CreateCompressedUpdateBlock(part, updateFlags);
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
compressedUpdateBlocks.Value.Add(compressedBlock);
compressedUpdates.Value.Add(update); compressedUpdates.Value.Add(update);
} }
else else
@ -3842,6 +3864,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
&& part.ParentGroup.HasPrivateAttachmentPoint && part.ParentGroup.HasPrivateAttachmentPoint
&& part.ParentGroup.AttachedAvatar != AgentId) && part.ParentGroup.AttachedAvatar != AgentId)
continue; continue;
// If the part has since been deleted, then drop the update. In the case of attachments,
// this is to avoid spurious updates to other viewers since post-processing of attachments
// has to change the IsAttachment flag for various reasons (which will end up in a pass
// of the test above).
//
// Actual deletions (kills) happen in another method.
if (part.ParentGroup.IsDeleted)
continue;
} }
terseUpdateBlocks.Value.Add(terseUpdateBlock); terseUpdateBlocks.Value.Add(terseUpdateBlock);

View File

@ -628,6 +628,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{ {
m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
sp.RemoveAttachment(group); sp.RemoveAttachment(group);
m_scene.DeleteSceneObject(group, false);
// Prepare sog for storage // Prepare sog for storage
group.AttachedAvatar = UUID.Zero; group.AttachedAvatar = UUID.Zero;
@ -636,7 +637,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.AbsolutePosition = group.RootPart.AttachedPos; group.AbsolutePosition = group.RootPart.AttachedPos;
UpdateKnownItem(sp, group, true); UpdateKnownItem(sp, group, true);
m_scene.DeleteSceneObject(group, false);
return; return;
} }

View File

@ -187,8 +187,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene(); TestScene scene = new SceneHelpers().SetupScene();
SceneObjectPart part = SceneHelpers.AddSceneObject(scene); SceneObjectPart part = SceneHelpers.AddSceneObject(scene);
Assert.That(part.ParentGroup.IsDeleted, Is.False);
scene.DeleteSceneObject(part.ParentGroup, false); scene.DeleteSceneObject(part.ParentGroup, false);
Assert.That(part.ParentGroup.IsDeleted, Is.True);
SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
Assert.That(retrievedPart, Is.Null); Assert.That(retrievedPart, Is.Null);
} }
@ -219,8 +224,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(retrievedPart, Is.Not.Null); Assert.That(retrievedPart, Is.Not.Null);
Assert.That(part.ParentGroup.IsDeleted, Is.False);
sogd.InventoryDeQueueAndDelete(); sogd.InventoryDeQueueAndDelete();
Assert.That(part.ParentGroup.IsDeleted, Is.True);
SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId);
Assert.That(retrievedPart2, Is.Null); Assert.That(retrievedPart2, Is.Null);
} }