Skip to content

Commit

Permalink
Added stack overflow handing, fixes #709
Browse files Browse the repository at this point in the history
  • Loading branch information
nickbattle committed Nov 29, 2019
1 parent 98065ea commit c29570c
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,37 @@ protected String format(String indent, Context what)
return sb.toString();
}

/**
* This is used by the stack overflow processing in Function/OperationValue.
* It is intended to print the frame titles without recursing.
* @param out
*/

private static final int FRAMES_LIMIT = 100;

public void printStackFrames(PrintWriter out)
{
Context frame = this;
out.print(format("\t", frame));
int count = 0;

while (frame.outer != null)
{
if (++count < FRAMES_LIMIT)
{
out.println("In context of " + frame.title + " " + frame.location);
}
else if (count == FRAMES_LIMIT)
{
out.println("...");
}

frame = frame.outer; // NB. DON'T RECURSE!
}

out.println("In context of " + frame.title);
}

public void printStackTrace(PrintWriter out, boolean variables)
{
if (outer == null) // Don't expand initial context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,17 +270,50 @@ public String toString()
return type.toString();
}

private static Integer stackUnwind = null;
private static final int UNWIND_COUNT = 20; // Needed by printStackFrames

private ContextException stackOverflow(StackOverflowError e, Context ctxt)
{
if (stackUnwind == null) // First time
{
stackUnwind = new Integer(UNWIND_COUNT);
}
else if (--stackUnwind <= 0)
{
Console.out.printf("Stack overflow %s\n", location);
ctxt.printStackFrames(Console.out);
return new ContextException(4174, "Stack overflow", location, ctxt);
}

throw e; // Unwind further to make space for printStackFrames
}

public Value eval(ILexLocation from, Value arg, Context ctxt)
throws AnalysisException
{
ValueList args = new ValueList(arg);
return eval(from, args, ctxt, null);
try
{
ValueList args = new ValueList(arg);
return eval(from, args, ctxt, null);
}
catch (StackOverflowError e)
{
throw stackOverflow(e, ctxt);
}
}

public Value eval(ILexLocation from, ValueList argValues, Context ctxt)
throws AnalysisException
{
return eval(from, argValues, ctxt, null);
try
{
return eval(from, argValues, ctxt, null);
}
catch (StackOverflowError e)
{
throw stackOverflow(e, ctxt);
}
}

public void setSelf(ObjectValue self)
Expand All @@ -304,6 +337,8 @@ public void setClass(SClassDefinition classdef)
public Value eval(ILexLocation from, ValueList argValues, Context ctxt,
Context sctxt) throws AnalysisException
{
stackUnwind = null;

if (uninstantiated)
{
abort(3033, "Polymorphic function has not been instantiated: "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.overture.interpreter.runtime.ClassContext;
import org.overture.interpreter.runtime.ClassInterpreter;
import org.overture.interpreter.runtime.Context;
import org.overture.interpreter.runtime.ContextException;
import org.overture.interpreter.runtime.Interpreter;
import org.overture.interpreter.runtime.ModuleInterpreter;
import org.overture.interpreter.runtime.ObjectContext;
Expand Down Expand Up @@ -254,25 +255,51 @@ public void prepareGuard(ObjectContext ctxt)
}
}

private static Integer stackUnwind = null;
private static final int UNWIND_COUNT = 20; // Needed by printStackFrames

private ContextException stackOverflow(ILexLocation location, StackOverflowError e, Context ctxt)
{
if (stackUnwind == null) // First time
{
stackUnwind = new Integer(UNWIND_COUNT);
}
else if (--stackUnwind <= 0)
{
Console.out.printf("Stack overflow %s\n", location);
ctxt.printStackFrames(Console.out);
return new ContextException(4174, "Stack overflow", location, ctxt);
}

throw e; // Unwind further to make space for printStackFrames
}

public Value eval(ILexLocation from, ValueList argValues, Context ctxt)
throws AnalysisException
{
// Note args cannot be Updateable, so we convert them here. This means
// that TransactionValues pass the local "new" value to the far end.
ValueList constValues = argValues.getConstant();

if (Settings.dialect == Dialect.VDM_RT)
try
{
if (!isStatic && (ctxt.threadState.CPU != self.getCPU() || isAsync))
// Note args cannot be Updateable, so we convert them here. This means
// that TransactionValues pass the local "new" value to the far end.
ValueList constValues = argValues.getConstant();

if (Settings.dialect == Dialect.VDM_RT)
{
return asyncEval(constValues, ctxt);
if (!isStatic && (ctxt.threadState.CPU != self.getCPU() || isAsync))
{
return asyncEval(constValues, ctxt);
} else
{
return localEval(from, constValues, ctxt, true);
}
} else
{
return localEval(from, constValues, ctxt, true);
}
} else
}
catch (StackOverflowError e)
{
return localEval(from, constValues, ctxt, true);
throw stackOverflow(from, e, ctxt);
}
}

Expand Down

0 comments on commit c29570c

Please sign in to comment.