From e131e73652cf6ed2407e41c7d83dc67f49ca23ee Mon Sep 17 00:00:00 2001
From: Oren Hurvitz
Date: Wed, 29 Jan 2014 16:14:27 +0200
Subject: Run slow operations in a separate thread, instead of using
FireAndForget (which has a 1-minute timeout)
Resolves http://opensimulator.org/mantis/view.php?id=6945
---
OpenSim/Framework/Util.cs | 23 ++++++++++++++++++++++
.../Archiver/InventoryArchiveWriteRequest.cs | 2 +-
.../Inventory/LocalInventoryServiceConnector.cs | 4 ++--
.../World/Archiver/ArchiveWriteRequest.cs | 2 +-
.../CoreModules/World/Archiver/AssetsRequest.cs | 6 +++---
OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++--
7 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index b39dc5f..c9930fb 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2320,6 +2320,29 @@ namespace OpenSim.Framework
#endregion FireAndForget Threading Pattern
///
+ /// Run the callback on a different thread, outside the thread pool. This is used for tasks
+ /// that may take a long time.
+ ///
+ public static void RunThreadNoTimeout(WaitCallback callback, string name, object obj)
+ {
+ Thread t = new Thread(delegate()
+ {
+ try
+ {
+ Culture.SetCurrentCulture();
+ callback(obj);
+ }
+ catch (Exception e)
+ {
+ m_log.Error("Exception in thread " + name, e);
+ }
+ });
+
+ t.Name = name;
+ t.Start();
+ }
+
+ ///
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
/// and negative every 24.9 days. This trims down TickCount so it doesn't wrap
/// for the callers.
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 4292719..d15703e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
options, ReceivedAllAssets);
- Util.FireAndForget(o => ar.Execute());
+ Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null);
}
else
{
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 99913a9..6832b1f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -193,12 +193,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
// Protect ourselves against the caller subsequently modifying the items list
List items = new List(invCol.Items);
- Util.FireAndForget(delegate
+ Util.RunThreadNoTimeout(delegate
{
foreach (InventoryItemBase item in items)
if (!string.IsNullOrEmpty(item.CreatorData))
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
- });
+ }, "GetFolderContent", null);
}
return invCol;
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index cd95ee9..136a16e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_rootScene.AssetService, m_rootScene.UserAccountService,
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
- Util.FireAndForget(o => ar.Execute());
+ Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null);
// CloseArchive() will be called from ReceivedAllAssets()
}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 2d0da61..4f428c3 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_requestState = RequestState.Running;
m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
-
+
// We can stop here if there are no assets to fetch
if (m_repliesRequired == 0)
{
@@ -226,7 +226,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
finally
{
if (timedOut)
- Util.FireAndForget(PerformAssetsRequestCallback, true);
+ Util.RunThreadNoTimeout(PerformAssetsRequestCallback, "AssetsRequestCallback", true);
}
}
@@ -295,7 +295,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// We want to stop using the asset cache thread asap
// as we now need to do the work of producing the rest of the archive
- Util.FireAndForget(PerformAssetsRequestCallback, false);
+ Util.RunThreadNoTimeout(PerformAssetsRequestCallback, "AssetsRequestCallback", false);
}
else
{
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 51f6c5e..726d8e2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1509,7 +1509,7 @@ namespace OpenSim.Region.Framework.Scenes
{
tmpMS = Util.EnvironmentTickCount();
m_cleaningTemps = true;
- Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
+ Util.RunThreadNoTimeout(delegate { CleanTempObjects(); m_cleaningTemps = false; }, "CleanTempObjects", null);
tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
}
@@ -1682,7 +1682,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!m_backingup)
{
m_backingup = true;
- Util.FireAndForget(BackupWaitCallback);
+ Util.RunThreadNoTimeout(BackupWaitCallback, "BackupWaitCallback", null);
}
}
@@ -1695,7 +1695,7 @@ namespace OpenSim.Region.Framework.Scenes
}
///
- /// Wrapper for Backup() that can be called with Util.FireAndForget()
+ /// Wrapper for Backup() that can be called with Util.RunThreadNoTimeout()
///
private void BackupWaitCallback(object o)
{
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 64c464d..080cdb4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3201,7 +3201,7 @@ namespace OpenSim.Region.Framework.Scenes
public void SendInitialDataToMe()
{
// Send all scene object to the new client
- Util.FireAndForget(delegate
+ Util.RunThreadNoTimeout(delegate
{
// we created a new ScenePresence (a new child agent) in a fresh region.
// Request info about all the (root) agents in this region
@@ -3216,7 +3216,7 @@ namespace OpenSim.Region.Framework.Scenes
((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
}
- });
+ }, "SendInitialDataToMe", null);
}
///
--
cgit v1.1