Yengine: try fix changing scripts running state if the have long events

0.9.1.0-post-fixes
UbitUmarov 2019-04-01 13:58:41 +01:00
parent 3b63699b9d
commit 7f55db72d2
4 changed files with 96 additions and 23 deletions

View File

@ -1535,15 +1535,38 @@ namespace OpenSim.Region.ScriptEngine.Yengine
*/ */
public void QueueToStart(XMRInstance inst) public void QueueToStart(XMRInstance inst)
{ {
if(inst.m_IState != XMRInstState.ONSTARTQ) if (inst.m_IState != XMRInstState.ONSTARTQ)
throw new Exception("bad state"); throw new Exception("bad state");
lock(m_StartQueue) lock (m_StartQueue)
m_StartQueue.InsertTail(inst); m_StartQueue.InsertTail(inst);
WakeUpOne(); WakeUpOne();
} }
public void QueueToYield(XMRInstance inst)
{
if (inst.m_IState != XMRInstState.ONYIELDQ)
throw new Exception("bad state");
lock (m_YieldQueue)
m_YieldQueue.InsertTail(inst);
WakeUpOne();
}
public void RemoveFromSleep(XMRInstance inst)
{
lock (m_SleepQueue)
{
if (inst.m_IState != XMRInstState.ONSLEEPQ)
return;
m_SleepQueue.Remove(inst);
inst.m_IState = XMRInstState.REMDFROMSLPQ;
}
}
/** /**
* @brief A script may be sleeping, in which case we wake it. * @brief A script may be sleeping, in which case we wake it.
*/ */

View File

@ -363,8 +363,33 @@ namespace OpenSim.Region.ScriptEngine.Yengine
lock(m_QueueLock) lock(m_QueueLock)
{ {
m_Running = value; m_Running = value;
if(!value) if(value)
{ {
if (m_IState == XMRInstState.SUSPENDED && m_SuspendCount == 0)
{
if(eventCode != ScriptEventCode.None)
{
m_IState = XMRInstState.ONYIELDQ;
m_Engine.QueueToYield(this);
}
else if ((m_EventQueue != null) && (m_EventQueue.First != null))
{
m_IState = XMRInstState.ONSTARTQ;
m_Engine.QueueToStart(this);
}
else
m_IState = XMRInstState.IDLE;
}
else if(m_SuspendCount != 0)
m_IState = XMRInstState.IDLE;
}
else
{
if(m_IState == XMRInstState.ONSLEEPQ)
{
m_Engine.RemoveFromSleep(this);
m_IState = XMRInstState.SUSPENDED;
}
EmptyEventQueues(); EmptyEventQueues();
} }
} }

View File

@ -80,10 +80,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
!m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state
return; return;
// Not running means we ignore any incoming events. // Not running means we ignore any incoming events.
// But queue if still constructing because m_Running is not yet valid. // But queue if still constructing because m_Running is not yet valid.
if(!m_Running && !construct) if(!m_Running && !construct)
{
if(m_IState == XMRInstState.SUSPENDED)
{
if(evc == ScriptEventCode.state_entry && m_EventQueue.Count == 0)
{
LinkedListNode<EventParams> llns = new LinkedListNode<EventParams>(evt);
m_EventQueue.AddFirst(llns);
}
}
return; return;
}
if(m_minEventDelay != 0) if(m_minEventDelay != 0)
{ {
@ -250,13 +261,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
return XMRInstState.SUSPENDED; return XMRInstState.SUSPENDED;
} }
// Make sure we aren't being migrated in or out and prevent that // Make sure we aren't being migrated in or out and prevent that
// whilst we are in here. If migration has it locked, don't call // whilst we are in here. If migration has it locked, don't call
// back right away, delay a bit so we don't get in infinite loop. // back right away, delay a bit so we don't get in infinite loop.
m_RunOnePhase = "lock m_RunLock"; m_RunOnePhase = "lock m_RunLock";
if(!Monitor.TryEnter(m_RunLock)) if(!Monitor.TryEnter(m_RunLock))
{ {
m_SleepUntil = now.AddMilliseconds(3); m_SleepUntil = now.AddMilliseconds(15);
m_RunOnePhase = "return was locked"; m_RunOnePhase = "return was locked";
return XMRInstState.ONSLEEPQ; return XMRInstState.ONSLEEPQ;
} }
@ -273,6 +284,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine
return XMRInstState.DISPOSED; return XMRInstState.DISPOSED;
} }
if(!m_Running)
{
m_RunOnePhase = "return is not running";
return XMRInstState.SUSPENDED;
}
// Do some more of the last event if it didn't finish. // Do some more of the last event if it didn't finish.
if(this.eventCode != ScriptEventCode.None) if(this.eventCode != ScriptEventCode.None)
{ {
@ -325,10 +342,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
if(m_EventQueue.First != null) if(m_EventQueue.First != null)
{ {
evt = m_EventQueue.First.Value; evt = m_EventQueue.First.Value;
if(m_DetachQuantum > 0) evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName);
if (m_DetachQuantum > 0)
{ {
evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode),
evt.EventName);
if(evc != ScriptEventCode.attach) if(evc != ScriptEventCode.attach)
{ {
// This is the case where the attach event // This is the case where the attach event
@ -343,8 +359,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
} }
} }
m_EventQueue.RemoveFirst(); m_EventQueue.RemoveFirst();
evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode),
evt.EventName);
if((int)evc >= 0) if((int)evc >= 0)
m_EventCounts[(int)evc]--; m_EventCounts[(int)evc]--;
} }
@ -730,11 +744,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
case XMRInstState.DISPOSED: case XMRInstState.DISPOSED:
return; return;
// Some other thread is already resetting it, let it finish. // Some other thread is already resetting it, let it finish.
case XMRInstState.RESETTING: case XMRInstState.RESETTING:
return; return;
case XMRInstState.SUSPENDED:
break;
default: default:
throw new Exception("bad state"); throw new Exception("bad state");
} }
@ -744,17 +761,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
{ {
CheckRunLockInvariants(true); CheckRunLockInvariants(true);
// No other thread should have transitioned it from RESETTING. // No other thread should have transitioned it from RESETTING.
if(m_IState != XMRInstState.RESETTING) if (m_IState != XMRInstState.SUSPENDED)
throw new Exception("bad state"); {
if (m_IState != XMRInstState.RESETTING)
throw new Exception("bad state");
// Mark it idle now so it can get queued to process new stuff. m_IState = XMRInstState.IDLE;
m_IState = XMRInstState.IDLE; }
// Reset everything and queue up default's start_entry() event. // Reset everything and queue up default's start_entry() event.
ClearQueue(); ClearQueue();
ResetLocked("external Reset"); ResetLocked("external Reset");
// Mark it idle now so it can get queued to process new stuff.
CheckRunLockInvariants(true); CheckRunLockInvariants(true);
} }
} }

View File

@ -166,7 +166,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
if(inst == null) if(inst == null)
break; break;
if(inst.m_IState != XMRInstState.ONSTARTQ) if (inst.m_IState == XMRInstState.SUSPENDED)
continue;
if (inst.m_IState != XMRInstState.ONSTARTQ)
throw new Exception("bad state"); throw new Exception("bad state");
RunInstance(inst, tid); RunInstance(inst, tid);
if(m_SuspendScriptThreadFlag || m_Exiting) if(m_SuspendScriptThreadFlag || m_Exiting)
@ -187,7 +189,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
if(inst != null) if(inst != null)
{ {
if(inst.m_IState != XMRInstState.ONYIELDQ) if (inst.m_IState == XMRInstState.SUSPENDED)
continue;
if (inst.m_IState != XMRInstState.ONYIELDQ)
throw new Exception("bad state"); throw new Exception("bad state");
RunInstance(inst, tid); RunInstance(inst, tid);
continue; continue;