From 67432fcbf2b9ad58e83eb55f789c28ffd9ab572b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 26 Oct 2012 23:08:59 +0100 Subject: [PATCH 1/2] Fix "save iar" hanging permanently if the asset request phase times out. Unlike "save oar", this was happening on the same thread as the original request. The timeout happens on another so the original thread is never aborted. On "save oar" this leaves the thread hanging (still bad) but on "save iar" it left the console thread hanging. Temporary fix is to make "save iar" do asset request on a separate thread, like "save oar". Longer term fix will be to restructure asset save to use a ManualResetEvent rather than a separate timeout timer. --- .../Archiver/InventoryArchiveWriteRequest.cs | 13 ++++++---- .../Tests/InventoryArchiveTestCase.cs | 26 ++++++++++++++----- .../Archiver/Tests/InventoryArchiverTests.cs | 4 +-- .../World/Archiver/AssetsRequest.cs | 4 +++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 6587eadf57..d13b4a0a38 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -337,11 +337,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets).Execute(); + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets); + + Util.FireAndForget(o => ar.Execute()); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 1056865590..00727a45a6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -82,7 +82,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected string m_item1Name = "Ray Gun Item"; protected string m_coaItemName = "Coalesced Item"; - + + [TestFixtureSetUp] + public void FixtureSetup() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + + ConstructDefaultIarBytesForTestLoad(); + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [SetUp] public override void SetUp() { @@ -90,12 +108,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests m_iarStream = new MemoryStream(m_iarStreamBytes); } - [TestFixtureSetUp] - public void FixtureSetup() - { - ConstructDefaultIarBytesForTestLoad(); - } - protected void ConstructDefaultIarBytesForTestLoad() { // log4net.Config.XmlConfigurator.Configure(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 12a05b3df5..06f6e49ab6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiverTests : InventoryArchiveTestCase - { + { protected TestScene m_scene; protected InventoryArchiverModule m_archiverModule; @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestLoadCoalesecedItem() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 57872790b2..103eb4792b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -129,6 +129,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_options = options; m_repliesRequired = uuids.Count; + // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread + // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received + // so we can properly abort that thread. Or request all assets synchronously, though that would be a more + // radical change m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); m_requestCallbackTimer.AutoReset = false; m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); From 3531f29a6a81cd9106080a38d68a4b8b0e347db5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 27 Oct 2012 00:24:25 +0100 Subject: [PATCH 2/2] minor: Fix verbose IAR save message to make it a bit clearer that item data is being saved at that point, not asset data. --- .../Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d13b4a0a38..d0e88f697f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (options.ContainsKey("verbose")) m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem);