diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d03b464082..a2fceb7f03 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -290,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes
m_items.LockItemsForWrite(false);
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
- StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID));
+ StoreScriptErrors(item.ItemID, null);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
return;
@@ -319,7 +319,7 @@ namespace OpenSim.Region.Framework.Scenes
string script = Utils.BytesToString(asset.Data);
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
- StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID));
+ StoreScriptErrors(item.ItemID, null);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
}
@@ -388,11 +388,22 @@ namespace OpenSim.Region.Framework.Scenes
///
/// Start a script which is in this prim's inventory.
+ /// Some processing may occur in the background, but this routine returns asap.
///
///
/// A
///
public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
+ {
+ lock (m_scriptErrors)
+ {
+ // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
+ m_scriptErrors.Remove(itemId);
+ }
+ CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
+ }
+
+ private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
{
m_items.LockItemsForRead(true);
if (m_items.ContainsKey(itemId))
@@ -425,25 +436,38 @@ namespace OpenSim.Region.Framework.Scenes
}
+ ///
+ /// Start a script which is in this prim's inventory and return any compilation error messages.
+ ///
+ ///
+ /// A
+ ///
public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
{
ArrayList errors;
+ // Indicate to CreateScriptInstanceInternal() we want it to
+ // post any compilation/loading error messages
lock (m_scriptErrors)
{
- m_scriptErrors.Remove(itemId);
+ m_scriptErrors[itemId] = null;
}
- CreateScriptInstance(itemId, startParam, postOnRez, engine, stateSource);
+
+ // Perform compilation/loading
+ CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
+
+ // Wait for and retrieve any errors
lock (m_scriptErrors)
{
- while (!m_scriptErrors.TryGetValue(itemId, out errors))
+ while ((errors = m_scriptErrors[itemId]) == null)
{
if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
{
m_log.ErrorFormat(
"[PRIM INVENTORY]: " +
"timedout waiting for script {0} errors", itemId);
- if (!m_scriptErrors.TryGetValue(itemId, out errors))
+ errors = m_scriptErrors[itemId];
+ if (errors == null)
{
errors = new ArrayList(1);
errors.Add("timedout waiting for errors");
@@ -455,14 +479,49 @@ namespace OpenSim.Region.Framework.Scenes
}
return errors;
}
+
+ // Signal to CreateScriptInstanceEr() that compilation/loading is complete
private void StoreScriptErrors(UUID itemId, ArrayList errors)
{
+ lock (m_scriptErrors)
+ {
+ // If compilation/loading initiated via CreateScriptInstance(),
+ // it does not want the errors, so just get out
+ if (!m_scriptErrors.ContainsKey(itemId))
+ {
+ return;
+ }
+
+ // Initiated via CreateScriptInstanceEr(), if we know what the
+ // errors are, save them and wake CreateScriptInstanceEr().
+ if (errors != null)
+ {
+ m_scriptErrors[itemId] = errors;
+ System.Threading.Monitor.PulseAll(m_scriptErrors);
+ return;
+ }
+ }
+
+ // Initiated via CreateScriptInstanceEr() but we don't know what
+ // the errors are yet, so retrieve them from the script engine.
+ // This may involve some waiting internal to GetScriptErrors().
+ errors = GetScriptErrors(itemId);
+
+ // Get a default non-null value to indicate success.
+ if (errors == null)
+ {
+ errors = new ArrayList();
+ }
+
+ // Post to CreateScriptInstanceEr() and wake it up
lock (m_scriptErrors)
{
m_scriptErrors[itemId] = errors;
System.Threading.Monitor.PulseAll(m_scriptErrors);
}
}
+
+ // Like StoreScriptErrors(), but just posts a single string message
private void StoreScriptError(UUID itemId, string message)
{
ArrayList errors = new ArrayList(1);