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
0.8.0.3
Oren Hurvitz 2014-01-29 16:14:27 +02:00
parent 84d7227dfd
commit e131e73652
7 changed files with 35 additions and 12 deletions

View File

@ -2319,6 +2319,29 @@ namespace OpenSim.Framework
#endregion FireAndForget Threading Pattern #endregion FireAndForget Threading Pattern
/// <summary>
/// Run the callback on a different thread, outside the thread pool. This is used for tasks
/// that may take a long time.
/// </summary>
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();
}
/// <summary> /// <summary>
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive /// 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 /// and negative every 24.9 days. This trims down TickCount so it doesn't wrap

View File

@ -356,7 +356,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
options, ReceivedAllAssets); options, ReceivedAllAssets);
Util.FireAndForget(o => ar.Execute()); Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null);
} }
else else
{ {

View File

@ -193,12 +193,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
// Protect ourselves against the caller subsequently modifying the items list // Protect ourselves against the caller subsequently modifying the items list
List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
Util.FireAndForget(delegate Util.RunThreadNoTimeout(delegate
{ {
foreach (InventoryItemBase item in items) foreach (InventoryItemBase item in items)
if (!string.IsNullOrEmpty(item.CreatorData)) if (!string.IsNullOrEmpty(item.CreatorData))
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
}); }, "GetFolderContent", null);
} }
return invCol; return invCol;

View File

@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_rootScene.AssetService, m_rootScene.UserAccountService, m_rootScene.AssetService, m_rootScene.UserAccountService,
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
Util.FireAndForget(o => ar.Execute()); Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null);
// CloseArchive() will be called from ReceivedAllAssets() // CloseArchive() will be called from ReceivedAllAssets()
} }

View File

@ -226,7 +226,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
finally finally
{ {
if (timedOut) 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 // 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 // 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 else
{ {

View File

@ -1509,7 +1509,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
tmpMS = Util.EnvironmentTickCount(); tmpMS = Util.EnvironmentTickCount();
m_cleaningTemps = true; m_cleaningTemps = true;
Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); Util.RunThreadNoTimeout(delegate { CleanTempObjects(); m_cleaningTemps = false; }, "CleanTempObjects", null);
tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
} }
@ -1682,7 +1682,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!m_backingup) if (!m_backingup)
{ {
m_backingup = true; m_backingup = true;
Util.FireAndForget(BackupWaitCallback); Util.RunThreadNoTimeout(BackupWaitCallback, "BackupWaitCallback", null);
} }
} }
@ -1695,7 +1695,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Wrapper for Backup() that can be called with Util.FireAndForget() /// Wrapper for Backup() that can be called with Util.RunThreadNoTimeout()
/// </summary> /// </summary>
private void BackupWaitCallback(object o) private void BackupWaitCallback(object o)
{ {

View File

@ -3201,7 +3201,7 @@ namespace OpenSim.Region.Framework.Scenes
public void SendInitialDataToMe() public void SendInitialDataToMe()
{ {
// Send all scene object to the new client // 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. // we created a new ScenePresence (a new child agent) in a fresh region.
// Request info about all the (root) agents in this region // Request info about all the (root) agents in this region
@ -3216,7 +3216,7 @@ namespace OpenSim.Region.Framework.Scenes
((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
} }
}); }, "SendInitialDataToMe", null);
} }
/// <summary> /// <summary>