private void MonitorScripts()
{
try
{
while (!StopScriptMonitoring)
{
DialPlanExecutingScript[] killScripts = null;
bool lockTaken = false;
Monitor.TryEnter(m_runningScripts, 100, ref lockTaken);
if (lockTaken)
{
try
{
killScripts = (from script in m_runningScripts
where
script.Complete ||
DateTime.Now > script.EndTime ||
DateTime.Now.Subtract(script.StartTime).TotalSeconds > ABSOLUTEMAX_SCRIPTPROCESSING_SECONDS
select script).ToArray();
}
finally
{
Monitor.Exit(m_runningScripts);
}
}
else
{
logger.Warn("Dialplan engine monitoring thread could not acquire a lock on the running scripts list.");
}
if (killScripts != null)
{
for (int index = 0; index < killScripts.Length; index++)
{
DialPlanExecutingScript killScript = killScripts[index];
DialPlanContext dialPlanContext = killScript.ExecutingDialPlanContext;
if (!killScript.Complete)
{
killScript.LogDelegate(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Long running dialplan script is being forcefully terminated.", killScript.Owner));
}
try
{
if (dialPlanContext != null && !dialPlanContext.IsAnswered)
{
// The dialplan script has finished but the client call has not been answered. There could have be an
// error executing the script or the dialplan could have completed without getting an answer.
if (!killScript.ExecutionError.IsNullOrBlank())
{
FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and had an execution error message of " + killScript.ExecutionError + ".", killScript.Owner));
dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, killScript.ExecutionError, null);
}
else if (killScript.LastFailureStatus != SIPResponseStatusCodesEnum.None)
{
FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and a last failure status of " + killScript.LastFailureStatus + " " + killScript.LastFailureReason + ".", killScript.Owner));
dialPlanContext.CallFailed(killScript.LastFailureStatus, killScript.LastFailureReason, null);
}
else
{
FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and with no last failure status.", killScript.Owner));
dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.TemporarilyUnavailable, null, null);
}
}
else
{
FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed with normal clearing.", killScript.Owner));
}
long gcMemory = GC.GetTotalMemory(false);
long physicalMemory = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;
FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan finished for " + killScript.Owner + ", gc memory=" + gcMemory + ", physical memory=" + physicalMemory + ", running script count=" + ScriptCount + ".", null));
}
catch (Exception finallyExcp)
{
logger.Error("Exception MonitorScripts Kill. " + finallyExcp.Message);
}
finally
{
try
{
/*if (killScript.DialPlanScriptThread != null && killScript.DialPlanScriptThread.IsAlive)
{
//logger.Debug("Aborting dialplan script thread.");
killScript.DialPlanScriptThread.Abort();
}*/
killScript.StopExecution();
}
catch (ThreadStateException) { } // This exception is thrown when aborting a thread in a suspended state and is expected behaviour.
catch (Exception killExcp)
{
logger.Error("Exception MonitorScripts aborting thread (" + killExcp.GetType().ToString() + "). " + killExcp.Message);
}
lock (m_runningScripts)
{
m_runningScripts.Remove(killScript);
}
logger.Debug("Executing script " + killScript.DialPlanScriptThread.Name + " removed from running scripts list, running script count=" + ScriptCount + ".");
}
}
}
Thread.Sleep(500);
}
if (StopScriptMonitoring)
{
if (m_runningScripts.Count > 0)
{
for (int index = 0; index < m_runningScripts.Count; index++)
{
if (m_runningScripts[index].DialPlanScriptThread != null && m_runningScripts[index].DialPlanScriptThread.IsAlive)
{
try
{
m_runningScripts[index].DialPlanScriptThread.Abort();
}
catch (Exception finalKill)
{
logger.Debug("Exception on script final kill. " + finalKill.Message);
}
}
}
}
}
}
catch (Exception excp)
{
logger.Error("Exception MonitorScripts. " + excp);
}
}