diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index b39dc5f3bf..c9930fbeea 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2319,6 +2319,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
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 429271916f..d15703eb73 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 99913a9b55..6832b1f06d 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 cd95ee9784..136a16e6c8 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 2d0da61145..4f428c35a6 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 51f6c5e6b8..726d8e261a 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 64c464d761..080cdb4e37 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);
}
///