diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index be007df135..453fd81689 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -392,6 +392,7 @@ namespace OpenSim.Region.Framework.Scenes return new ArrayList(); } + item.ScriptRunning = isScriptRunning; AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId); AssetService.Store(asset); @@ -399,10 +400,7 @@ namespace OpenSim.Region.Framework.Scenes // "[PRIM INVENTORY]: Stored asset {0} when updating item {1} in prim {2} for {3}", // asset.ID, item.Name, part.Name, remoteClient.Name); - if (isScriptRunning) - { - part.Inventory.RemoveScriptInstance(item.ItemID, false); - } + part.Inventory.RemoveScriptInstance(item.ItemID, false); // Update item with new asset item.AssetID = asset.FullID; @@ -412,14 +410,8 @@ namespace OpenSim.Region.Framework.Scenes part.SendPropertiesToClient(remoteClient); // Trigger rerunning of script (use TriggerRezScript event, see RezScript) - ArrayList errors = new ArrayList(); - - if (isScriptRunning) - { - // Needs to determine which engine was running it and use that - // - errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1); - } + // Needs to determine which engine was running it and use that + ArrayList errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1); // Tell anyone managing scripts that a script has been reloaded/changed EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID); @@ -2265,13 +2257,11 @@ namespace OpenSim.Region.Framework.Scenes destTaskItem.Name = srcTaskItem.Name; destTaskItem.InvType = srcTaskItem.InvType; destTaskItem.Type = srcTaskItem.Type; + destTaskItem.ScriptRunning = running != 0; destPart.Inventory.AddInventoryItemExclusive(destTaskItem, false); - if (running > 0) - { - destPart.Inventory.CreateScriptInstance(destTaskItem, start_param, false, DefaultScriptEngine, 1); - } + destPart.Inventory.CreateScriptInstance(destTaskItem, start_param, false, DefaultScriptEngine, 1); destPart.ParentGroup.ResumeScripts(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index b87e5658e2..07bd40bb1f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -637,10 +637,6 @@ namespace OpenSim.Region.Framework.Scenes /// Handle a client request to update the inventory folder /// /// - /// FIXME: We call add new inventory folder because in the data layer, we happen to use an SQL REPLACE - /// so this will work to rename an existing folder. Needless to say, to rely on this is very confusing, - /// and needs to be changed. - /// /// /// /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index e90cd1503e..f3d0bf2186 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -78,8 +78,7 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) - scriptsStarted - += parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); + scriptsStarted += parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); } return scriptsStarted; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d91f84afe1..e982cef7cf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -530,10 +530,8 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, itemID, script, startParam, postOnRez, engine, stateSource); StoreScriptErrors(itemID, null); - if (!item.ScriptRunning) - m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, itemID); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); + //if (item.ScriptRunning) + m_part.ParentGroup.AddActiveScriptCount(1); return true; } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 19a7a707c0..2278322135 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -316,7 +316,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_assetUuidsToInspect.Contains(uuid)) return false; - // m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); + //m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); GatheredUuids[uuid] = type; return true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 6726e035c2..0e173c4d4b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -408,10 +408,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (ShuttingDown) return; + if (m_startOnInit) + Start(); + if (m_startedFromSavedState) { - if (m_startOnInit) - Start(); if (m_postOnRez) { PostEvent(new EventParams("on_rez", @@ -440,10 +441,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } else { - if (m_startOnInit) - Start(); - PostEvent(new EventParams("state_entry", - new Object[0], new DetectParams[0])); + if(Running & ScriptTask.ScriptRunning) + PostEvent(EventParams.StateEntryParams); + else + QueueEvent(EventParams.StateEntryParams); + if (m_postOnRez) { PostEvent(new EventParams("on_rez", @@ -676,8 +678,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance new DetectParams[0])); PostEvent(new EventParams("state", new Object[] { state }, new DetectParams[0])); - PostEvent(new EventParams("state_entry", new Object[0], - new DetectParams[0])); + PostEvent(EventParams.StateEntryParams); // Requeue the timer event after the state changing events if (lastTimerEv != null) EventQueue.Enqueue(lastTimerEv); @@ -690,6 +691,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance throw new EventAbortException(); } + public void QueueEvent(EventParams data) + { + lock (EventQueue) + { + // The only events that persist across state changes are timers + if (m_StateChangeInProgress && data.EventName != "timer") + return; + if (EventQueue.Count >= m_MaxScriptQueue) + return; + if (data.EventName == "timer") + { + if (m_TimerQueued) + return; + m_TimerQueued = true; + } + if (data.EventName == "control") + { + int held = ((LSL_Types.LSLInteger)data.Params[1]).value; + // int changed = ((LSL_Types.LSLInteger)data.Params[2]).value; + + // If the last message was a 0 (nothing held) + // and this one is also nothing held, drop it + // + if (m_LastControlLevel == held && held == 0) + return; + + // If there is one or more queued, then queue + // only changed ones, else queue unconditionally + // + if (m_ControlEventsInQueue > 0) + { + if (m_LastControlLevel == held) + return; + } + + m_LastControlLevel = held; + m_ControlEventsInQueue++; + } + + if (data.EventName == "collision") + { + if (m_CollisionInQueue) + return; + if (data.DetectParams == null) + return; + + m_CollisionInQueue = true; + } + EventQueue.Enqueue(data); + } + } + /// /// Post an event to this script instance. /// @@ -1088,13 +1141,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance part.CollisionSound = UUID.Zero; part.RemoveScriptTargets(ItemID); part.SetScriptEvents(ItemID, m_Script.GetStateEventFlags(State)); - if (running) + if (running & ScriptTask.ScriptRunning) + { Start(); - + PostEvent(EventParams.StateEntryParams); + } + else + QueueEvent(EventParams.StateEntryParams); m_SaveState = StatePersistedHere; - - PostEvent(new EventParams("state_entry", - new Object[0], new DetectParams[0])); } [DebuggerNonUserCode] //Stops the VS debugger from farting in this function diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 40c523f16f..7538225e2f 100755 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1287,7 +1287,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Create the object record if ((!m_Scripts.ContainsKey(itemID)) || (m_Scripts[itemID].AssetID != assetID)) { - bool attachDomains = m_AttachmentsDomainLoading && part.ParentGroup.IsAttachmentCheckFull(); UUID appDomain = part.ParentGroup.RootPart.UUID; @@ -1533,14 +1532,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine lock (m_CompileDict) m_CompileDict.Remove(itemID); - bool runIt; - if (m_runFlags.TryGetValue(itemID, out runIt)) + bool runIt = instance.ScriptTask.ScriptRunning; + if (m_runFlags.TryGetValue(itemID, out bool flagrunIt)) { - if (!runIt) - StopScript(itemID); + runIt &= flagrunIt; m_runFlags.Remove(itemID); } + if (!runIt) + StopScript(itemID); + return true; } @@ -1880,8 +1881,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) { + if (instance.ScriptTask != null) + instance.ScriptTask.ScriptRunning = running; + if (running) - instance.Start(); + { + instance.Start(); + } else { if(self) @@ -2256,82 +2262,81 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (World.m_trustBinaries) { XmlNodeList assemL = rootE.GetElementsByTagName("Assembly"); - - if (assemL.Count != 1) - return false; - - XmlElement assemE = (XmlElement)assemL[0]; - - string fn = assemE.GetAttribute("Filename"); - string base64 = assemE.InnerText; - - string path = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); - path = Path.Combine(path, fn); - - if (!File.Exists(path)) + if (assemL.Count > 0) { - Byte[] filedata = Convert.FromBase64String(base64); + XmlElement assemE = (XmlElement)assemL[0]; - try + string fn = assemE.GetAttribute("Filename"); + string base64 = assemE.InnerText; + + string path = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); + path = Path.Combine(path, fn); + + if (!File.Exists(path)) { - using (FileStream fs = File.Create(path)) + Byte[] filedata = Convert.FromBase64String(base64); + + try { -// m_log.DebugFormat("[XEngine]: Writing assembly file {0}", path); - - fs.Write(filedata, 0, filedata.Length); - } - } - catch (IOException ex) - { - // if there already exists a file at that location, it may be locked. - m_log.ErrorFormat("[XEngine]: Error whilst writing assembly file {0}, {1}", path, ex.Message); - } - - string textpath = path + ".text"; - try - { - using (FileStream fs = File.Create(textpath)) - { - using (StreamWriter sw = new StreamWriter(fs)) + using (FileStream fs = File.Create(path)) { -// m_log.DebugFormat("[XEngine]: Writing .text file {0}", textpath); + // m_log.DebugFormat("[XEngine]: Writing assembly file {0}", path); - sw.Write(base64); + fs.Write(filedata, 0, filedata.Length); } } - } - catch (IOException ex) - { - // if there already exists a file at that location, it may be locked. - m_log.ErrorFormat("[XEngine]: Error whilst writing .text file {0}, {1}", textpath, ex.Message); - } - } - - XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); - if (mapL.Count > 0) - { - XmlElement mapE = (XmlElement)mapL[0]; - - string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); - mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); - - try - { - using (FileStream mfs = File.Create(mappath)) + catch (IOException ex) { - using (StreamWriter msw = new StreamWriter(mfs)) - { - // m_log.DebugFormat("[XEngine]: Writing linemap file {0}", mappath); + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: Error whilst writing assembly file {0}, {1}", path, ex.Message); + } - msw.Write(mapE.InnerText); + string textpath = path + ".text"; + try + { + using (FileStream fs = File.Create(textpath)) + { + using (StreamWriter sw = new StreamWriter(fs)) + { + // m_log.DebugFormat("[XEngine]: Writing .text file {0}", textpath); + + sw.Write(base64); + } } } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: Error whilst writing .text file {0}, {1}", textpath, ex.Message); + } } - catch (IOException ex) + + XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); + if (mapL.Count > 0) { - // if there already exists a file at that location, it may be locked. - m_log.Error( - string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex); + XmlElement mapE = (XmlElement)mapL[0]; + + string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); + mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); + + try + { + using (FileStream mfs = File.Create(mappath)) + { + using (StreamWriter msw = new StreamWriter(mfs)) + { + // m_log.DebugFormat("[XEngine]: Writing linemap file {0}", mappath); + + msw.Write(mapE.InnerText); + } + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.Error( + string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex); + } } } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs index 196eac3435..d658c4971a 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs @@ -322,7 +322,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine (((m_HeapSize % 0x100000) * 1000) >> 20).ToString("D3")); - m_SleepThread = StartMyThread(RunSleepThread, "Yengine sleep" + " (" + sceneName + ")", ThreadPriority.Normal); + m_SleepThread = StartMyThread(RunSleepThread, "Yengine sleep" + " (" + sceneName + ")", ThreadPriority.Normal, -1); for (int i = 0; i < numThreadScriptWorkers; i++) StartThreadWorker(i, m_workersPrio, sceneName); @@ -1304,6 +1304,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine instance.m_Item = item; instance.m_DescName = part.Name + ":" + item.Name; instance.m_IState = XMRInstState.CONSTRUCT; + instance.m_Running = item.ScriptRunning; lock(m_InstancesDict) { @@ -1413,19 +1414,28 @@ namespace OpenSim.Region.ScriptEngine.Yengine // Put it on the start queue so it will run any queued event handlers, // such as state_entry() or on_rez(). If there aren't any queued, it // will just go to idle state when RunOne() tries to dequeue an event. - lock(instance.m_QueueLock) - { - if(instance.m_IState != XMRInstState.CONSTRUCT) - throw new Exception("bad state"); - instance.m_IState = XMRInstState.ONSTARTQ; - if(!instance.m_Running) - instance.EmptyEventQueues(); - } // Declare which events the script's current state can handle. + ulong eventMask = instance.GetStateEventFlags(instance.stateCode); instance.m_Part.SetScriptEvents(instance.m_ItemID, eventMask); - QueueToStart(instance); + lock (instance.m_QueueLock) + { + if(instance.m_IState != XMRInstState.CONSTRUCT) + throw new Exception("bad state"); + + if (instance.m_Running) + { + instance.m_Item.ScriptRunning = true; + instance.m_IState = XMRInstState.ONSTARTQ; + QueueToStart(instance); + } + else + { + instance.m_Item.ScriptRunning = false; + instance.m_IState = XMRInstState.SUSPENDED; + } + } } public void OnRemoveScript(uint localID, UUID itemID) @@ -1512,15 +1522,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine { TraceCalls("[YEngine]: YEngine.OnGetScriptRunning({0},{1})", objectID.ToString(), itemID.ToString()); + bool curRunnning = instance.Running & instance.m_Item.ScriptRunning; IEventQueue eq = World.RequestModuleInterface(); if(eq == null) { - controllingClient.SendScriptRunningReply(objectID, itemID, - instance.Running); + controllingClient.SendScriptRunningReply(objectID, itemID, curRunnning); } else { - eq.ScriptRunningEvent(objectID, itemID, instance.Running, controllingClient.AgentId); + eq.ScriptRunningEvent(objectID, itemID, curRunnning, controllingClient.AgentId); } } } @@ -2033,10 +2043,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine /** * @brief Manage our threads. */ - public static Thread StartMyThread(ThreadStart start, string name, ThreadPriority priority) + public static Thread StartMyThread(ThreadStart start, string name, ThreadPriority priority, int stackSize) { m_log.Debug("[YEngine]: starting thread " + name); - Thread thread = WorkManager.StartThread(start, name, priority, false, false); + Thread thread = WorkManager.StartThread(start, name, priority, stackSize); return thread; } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs index f9cbf0ae44..e82a8af87b 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs @@ -363,7 +363,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(!File.Exists(m_StateFileName)) { - m_Running = true; // event processing is enabled eventCode = ScriptEventCode.None; // not processing any event // default state_entry() must initialize global variables @@ -393,7 +392,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine { File.Delete(m_StateFileName); - m_Running = true; // event processing is enabled eventCode = ScriptEventCode.None; // not processing any event // default state_entry() must initialize global variables @@ -406,7 +404,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine } // Post event(s) saying what caused the script to start. - //if(m_Running) + if(m_Running) { if(m_PostOnRez) { @@ -511,7 +509,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine // Get various attributes XmlElement runningN = (XmlElement)scriptStateN.SelectSingleNode("Running"); - m_Running = bool.Parse(runningN.InnerText); + m_Running &= bool.Parse(runningN.InnerText); XmlElement doGblInitN = (XmlElement)scriptStateN.SelectSingleNode("DoGblInit"); doGblInit = bool.Parse(doGblInitN.InnerText); diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs index c64e193322..e25bc044bf 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs @@ -401,11 +401,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine } else { - if(m_IState == XMRInstState.ONSLEEPQ) + if (m_IState == XMRInstState.ONSLEEPQ) { m_Engine.RemoveFromSleep(this); m_IState = XMRInstState.SUSPENDED; } + else if (m_IState == XMRInstState.IDLE) + m_IState = XMRInstState.SUSPENDED; + EmptyEventQueues(); } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs index 89bc2257c2..4b90ab8df3 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs @@ -66,35 +66,31 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(!m_eventCodeMap.TryGetValue(evt.EventName, out ScriptEventCode evc)) return; - // Put event on end of event queue. + if (((uint)evc >= (uint)m_HaveEventHandlers.Length) || !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state + return; + + // Put event on end of event queue. bool startIt = false; bool wakeIt = false; lock(m_QueueLock) { - bool construct = (m_IState == XMRInstState.CONSTRUCT); - // Ignore event if we don't even have such an handler in any state. // We can't be state-specific here because state might be different // by the time this event is dequeued and delivered to the script. - if(!construct && // make sure m_HaveEventHandlers is filled in - ((uint)evc < (uint)m_HaveEventHandlers.Length) && - !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state - return; - - // Not running means we ignore any incoming events. - // But queue if still constructing because m_Running is not yet valid. - - if(!m_Running && !construct) + if(m_IState != XMRInstState.CONSTRUCT) { - if(m_IState == XMRInstState.SUSPENDED) + if(!m_Running) { - if(evc == ScriptEventCode.state_entry && m_EventQueue.Count == 0) + if(m_IState == XMRInstState.SUSPENDED) { - LinkedListNode llns = new LinkedListNode(evt); - m_EventQueue.AddFirst(llns); + if(evc == ScriptEventCode.state_entry && m_EventQueue.Count == 0) + { + LinkedListNode llns = new LinkedListNode(evt); + m_EventQueue.AddFirst(llns); + } } + return; } - return; } if(m_minEventDelay != 0) @@ -138,23 +134,22 @@ namespace OpenSim.Region.ScriptEngine.Yengine } } - // Only so many of each event type allowed to queue. - if((uint)evc < (uint)m_EventCounts.Length) + if(evc == ScriptEventCode.timer) { - if(evc == ScriptEventCode.timer) - { - if(m_EventCounts[(int)evc] >= 1) - return; - } - else if(m_EventCounts[(int)evc] >= MAXEVENTQUEUE) + if (m_EventCounts[(int)evc] >= 1) return; - m_EventCounts[(int)evc]++; + m_EventQueue.AddLast(new LinkedListNode(evt)); + return; } - // Put event on end of instance's event queue. - LinkedListNode lln = new LinkedListNode(evt); - switch(evc) + if (m_EventCounts[(int)evc] >= MAXEVENTQUEUE) + return; + + m_EventCounts[(int)evc]++; + + LinkedListNode lln = new LinkedListNode(evt); + switch (evc) { // These need to go first. The only time we manually // queue them is for the default state_entry() and we @@ -170,7 +165,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine // of all others so the m_DetachQuantum won't run out // before attach(NULL_KEY) is executed. case ScriptEventCode.attach: - if(evt.Params[0].ToString() == UUID.Zero.ToString()) + if (evt.Params[0].ToString() == UUID.Zero.ToString()) { LinkedListNode lln2 = null; for(lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next) @@ -185,18 +180,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine else m_EventQueue.AddBefore(lln2, lln); - // If we're detaching, limit the qantum. This will also - // cause the script to self-suspend after running this - // event + // If we're detaching, limit the qantum. This will also + // cause the script to self-suspend after running this + // event m_DetachReady.Reset(); m_DetachQuantum = 100; } else m_EventQueue.AddLast(lln); - break; - // All others just go on end in the order queued. + // All others just go on end in the order queued. default: m_EventQueue.AddLast(lln); break; @@ -296,11 +290,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine //m_RunOnePhase = "return was locked"; return XMRInstState.ONSLEEPQ; } + try { //m_RunOnePhase = "check entry invariants"; CheckRunLockInvariants(true); - Exception e = null; // Maybe it has been Disposed() if(m_Part == null || m_Part.Inventory == null) @@ -315,8 +309,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine return XMRInstState.SUSPENDED; } - // Do some more of the last event if it didn't finish. - if(this.eventCode != ScriptEventCode.None) + Exception e = null; + + // Do some more of the last event if it didn't finish. + if (this.eventCode != ScriptEventCode.None) { lock(m_QueueLock) { @@ -347,7 +343,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine lock(m_QueueLock) { - // We can't get here unless the script has been resumed // after creation, then suspended again, and then had // an event posted to it. We just pretend there is no @@ -455,18 +450,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine // If not executing any event handler, there shouldn't be any saved stack frames. // If executing an event handler, there should be some saved stack frames. bool active = (stackFrames != null); - ScriptEventCode ec = this.eventCode; - if(((ec == ScriptEventCode.None) && active) || - ((ec != ScriptEventCode.None) && !active)) + if((active && (eventCode == ScriptEventCode.None)) || + (!active && (eventCode != ScriptEventCode.None))) { m_log.Error("CheckRunLockInvariants: script=" + m_DescName); - m_log.Error("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); + m_log.Error("CheckRunLockInvariants: eventcode=" + eventCode.ToString() + ", active=" + active.ToString()); //m_log.Error("CheckRunLockInvariants: m_RunOnePhase=" + m_RunOnePhase); //m_log.Error("CheckRunLockInvariants: lastec=" + lastEventCode + ", lastAct=" + lastActive + ", lastPhase=" + lastRunPhase); if(throwIt) - throw new Exception("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); + throw new Exception("CheckRunLockInvariants: eventcode=" + eventCode.ToString() + ", active=" + active.ToString()); } - //lastEventCode = ec; + //lastEventCode = eventCode; //lastActive = active; //lastRunPhase = m_RunOnePhase; } @@ -487,30 +481,30 @@ namespace OpenSim.Region.ScriptEngine.Yengine */ private Exception StartEventHandler(ScriptEventCode newEventCode, object[] newEhArgs) { - // We use this.eventCode == ScriptEventCode.None to indicate we are idle. - // So trying to execute ScriptEventCode.None might make a mess. + // We use this.eventCode == ScriptEventCode.None to indicate we are idle. + // So trying to execute ScriptEventCode.None might make a mess. if(newEventCode == ScriptEventCode.None) return new Exception("Can't process ScriptEventCode.None"); - // Silly to even try if there is no handler defined for this event. - if(((int)newEventCode >= 0) && (m_ObjCode.scriptEventHandlerTable[this.stateCode, (int)newEventCode] == null)) - return null; - - // The microthread shouldn't be processing any event code. - // These are assert checks so we throw them directly as exceptions. - if(this.eventCode != ScriptEventCode.None) + // The microthread shouldn't be processing any event code. + // These are assert checks so we throw them directly as exceptions. + if (eventCode != ScriptEventCode.None) throw new Exception("still processing event " + this.eventCode.ToString()); - // Save eventCode so we know what event handler to run in the microthread. - // And it also marks us busy so we can't be started again and this event lost. - this.eventCode = newEventCode; - this.ehArgs = newEhArgs; + // Silly to even try if there is no handler defined for this event. + if (((int)newEventCode >= 0) && (m_ObjCode.scriptEventHandlerTable[this.stateCode, (int)newEventCode] == null)) + return null; - // This calls ScriptUThread.Main() directly, and returns when Main() [indirectly] - // calls Suspend() or when Main() returns, whichever occurs first. - // Setting stackFrames = null means run the event handler from the beginning - // without doing any stack frame restores first. - this.stackFrames = null; + // Save eventCode so we know what event handler to run in the microthread. + // And it also marks us busy so we can't be started again and this event lost. + eventCode = newEventCode; + ehArgs = newEhArgs; + + // This calls ScriptUThread.Main() directly, and returns when Main() [indirectly] + // calls Suspend() or when Main() returns, whichever occurs first. + // Setting stackFrames = null means run the event handler from the beginning + // without doing any stack frame restores first. + stackFrames = null; return StartEx(); } @@ -526,8 +520,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine ScriptEventCode curevent = eventCode; eventCode = ScriptEventCode.None; stackFrames = null; + m_DetectParams = null; - if(m_Part == null || m_Part.Inventory == null) + if (m_Part == null || m_Part.Inventory == null) { //we are gone and don't know it still m_SleepUntil = DateTime.MaxValue; @@ -955,7 +950,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine */ public override void CheckRunWork() { - if(!suspendOnCheckRunHold && !suspendOnCheckRunTemp) + if (!suspendOnCheckRunHold && !suspendOnCheckRunTemp) { if(Util.GetTimeStampMS() - m_SliceStart < 60.0) return; diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs index 27312f2917..50bb65d299 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using OpenSim.Framework; using OpenSim.Framework.Monitoring; using System; using System.Collections.Generic; @@ -60,9 +61,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine { Thread thd; if(i >= 0) - thd = Yengine.StartMyThread(RunScriptThread, "YScript" + i.ToString() + " (" + sceneName +")", priority); + thd = Yengine.StartMyThread(RunScriptThread, "YScript" + i.ToString() + " (" + sceneName +")", priority, -1); else - thd = Yengine.StartMyThread(RunScriptThread, "YScript", priority); + thd = Yengine.StartMyThread(RunScriptThread, "YScript", priority, -1); lock(m_WakeUpLock) m_RunningInstances.Add(thd.ManagedThreadId, null); } @@ -122,6 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine int tid = System.Threading.Thread.CurrentThread.ManagedThreadId; ThreadStart thunk; XMRInstance inst; + bool didevent; m_ScriptThreadTID = tid; @@ -140,7 +142,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine else if(m_SuspendScriptThreadFlag && !m_Exiting) { Monitor.Wait(m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); - Yengine.UpdateMyThread(); continue; } } @@ -193,6 +194,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine continue; if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); + RunInstance(inst, tid); continue; } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs index 6f26243374..541d73936a 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using OpenSim.Framework; using System; using System.Collections.Generic; using System.Reflection;