Skip to content

Commit

Permalink
Only guard against stack overflow in the topmost ceval call
Browse files Browse the repository at this point in the history
  • Loading branch information
sjoelund authored and OpenModelica-Hudson committed Sep 2, 2015
1 parent 3fd5375 commit 7f30078
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Compiler/FrontEnd/ModelicaBuiltin.mo
Expand Up @@ -1637,7 +1637,7 @@ annotation(preferredView="text");
end getMessagesString;

record SourceInfo
String filename;
String fileName;
Boolean readonly;
Integer lineStart;
Integer columnStart;
Expand Down
2 changes: 2 additions & 0 deletions Compiler/Global/Global.mo
Expand Up @@ -56,6 +56,7 @@ constant Integer profilerTime2Index = 15;
constant Integer flagsIndex = 16;
constant Integer builtinGraphIndex = 17;
constant Integer rewriteRulesIndex = 18;
constant Integer stackoverFlowIndex = 19;

// indexes in System.tick
// ----------------------
Expand All @@ -73,6 +74,7 @@ public function initialize "Called to initialize global roots (when needed)"
algorithm
setGlobalRoot(instOnlyForcedFunctions, NONE());
setGlobalRoot(rewriteRulesIndex, NONE());
setGlobalRoot(stackoverFlowIndex, NONE());
end initialize;

annotation(__OpenModelica_Interface="util");
Expand Down
30 changes: 22 additions & 8 deletions Compiler/Script/CevalScript.mo
Expand Up @@ -2192,16 +2192,30 @@ function cevalCallFunctionEvaluateOrGenerate
output FCore.Cache outCache;
output Values.Value outValue;
output Option<GlobalScript.SymbolTable> outSymTab;
protected
Integer numCheckpoints;
algorithm
try
(outCache,outValue,outSymTab) := cevalCallFunctionEvaluateOrGenerate2(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction);
// Only add a stack overflow checkpoint for the top-most cevalCallFunctionEvaluateOrGenerate
if isNone(getGlobalRoot(Global.stackoverFlowIndex)) then
setGlobalRoot(Global.stackoverFlowIndex, SOME(1));
numCheckpoints:=ErrorExt.getNumCheckpoints();
try
StackOverflow.clearStacktraceMessages();
(outCache,outValue,outSymTab) := cevalCallFunctionEvaluateOrGenerate2(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction);
else
setGlobalRoot(Global.stackoverFlowIndex, NONE());
ErrorExt.rollbackNumCheckpoints(ErrorExt.getNumCheckpoints()-numCheckpoints);
Error.addInternalError("Stack overflow when evaluating function call: "+ExpressionDump.printExpStr(inExp)+"...\n"+stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), match inMsg local SourceInfo info; case Absyn.MSG(info) then info; else sourceInfo(); end match);
/* Do not fail or we can loop too much */
StackOverflow.clearStacktraceMessages();
outCache := inCache;
outSymTab := inSymTab;
outValue := Values.META_FAIL();
end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
setGlobalRoot(Global.stackoverFlowIndex, NONE());
else
Error.addInternalError("Stack overflow when evaluating function call: "+ExpressionDump.printExpStr(inExp)+"...\n"+stringDelimitList(StackOverflow.getStacktraceMessages(), "\n"), match inMsg local SourceInfo info; case Absyn.MSG(info) then info; else sourceInfo(); end match);
/* Do not fail or we can loop too much */
outCache := inCache;
outSymTab := inSymTab;
outValue := Values.META_FAIL();
end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
(outCache,outValue,outSymTab) := cevalCallFunctionEvaluateOrGenerate2(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction);
end if;
end cevalCallFunctionEvaluateOrGenerate;

function cevalCallFunctionEvaluateOrGenerate2
Expand Down
13 changes: 12 additions & 1 deletion Compiler/Util/Error.mo
Expand Up @@ -70,6 +70,10 @@ encapsulated package Error
public import Util;
public import Flags;

protected

import Config;

public
uniontype Severity "severity of message"
record INTERNAL "Error because of a failure in the tool" end INTERNAL;
Expand Down Expand Up @@ -1279,8 +1283,15 @@ public function addInternalError "
Used to make an internal error"
input String message;
input SourceInfo info;
protected
String filename;
algorithm
addSourceMessage(INTERNAL_ERROR, {message}, info);
if Config.getRunningTestsuite() then
SOURCEINFO(fileName=filename):=info;
addSourceMessage(INTERNAL_ERROR, {message}, SOURCEINFO(filename,false,0,0,0,0,0));
else
addSourceMessage(INTERNAL_ERROR, {message}, info);
end if;
end addInternalError;

annotation(__OpenModelica_Interface="util");
Expand Down
15 changes: 15 additions & 0 deletions Compiler/Util/ErrorExt.mo
Expand Up @@ -122,6 +122,21 @@ function clearMessages
external "C" ErrorImpl__clearMessages(OpenModelica.threadData()) annotation(Library = "omcruntime");
end clearMessages;

function getNumCheckpoints "Used to rollback/delete checkpoints without considering the identifier. Used to reset the error messages after a stack overflow exception."
output Integer n;
external "C" n=ErrorImpl__getNumCheckpoints(OpenModelica.threadData()) annotation(Library = "omcruntime");
end getNumCheckpoints;

function rollbackNumCheckpoints "Used to rollback/delete checkpoints without considering the identifier. Used to reset the error messages after a stack overflow exception."
input Integer n;
external "C" ErrorImpl__rollbackNumCheckpoints(OpenModelica.threadData(), n) annotation(Library = "omcruntime");
end rollbackNumCheckpoints;

function deleteNumCheckpoints "Used to rollback/delete checkpoints without considering the identifier. Used to reset the error messages after a stack overflow exception."
input Integer n;
external "C" ErrorImpl__deleteNumCheckpoints(OpenModelica.threadData(), n) annotation(Library = "omcruntime");
end deleteNumCheckpoints;

function setCheckpoint "sets a checkpoint for the error messages, so error messages can be rolled back (i.e. deleted) up to this point
A unique identifier for this checkpoint must be provided. It is checked when doing rollback or deletion"
input String id "uniqe identifier for the checkpoint (up to the programmer to guarantee uniqueness)";
Expand Down
5 changes: 5 additions & 0 deletions Compiler/Util/StackOverflow.mo
Expand Up @@ -33,6 +33,7 @@ encapsulated package StackOverflow

protected

import Config;
import System;

function unmangle
Expand Down Expand Up @@ -75,6 +76,10 @@ protected
String prev = "";
Integer n = 1, prevN = 1;
algorithm
if Config.getRunningTestsuite() then
symbols := {"[bt] [Symbols are not generated when running the test suite]"};
return;
end if;
for symbol in list(stripAddresses(s) for s in getStacktraceMessages()) loop
if prev == "" then

Expand Down
37 changes: 37 additions & 0 deletions Compiler/runtime/errorext.cpp
Expand Up @@ -284,6 +284,28 @@ extern void ErrorImpl__delCheckpoint(threadData_t *threadData,const char* id)
exit(-1);
}
}
extern void ErrorImpl__deleteNumCheckpoints(threadData_t *threadData, int n)
{
errorext_members *members = getMembers(threadData);
pair<int,string> cp;
// fprintf(stderr, "delCheckpoint(%s)\n",id); fflush(stderr);
if (members->checkPoints->size() < n) {
fprintf(stderr, "ERROREXT: calling ErrorImpl__rollbackNumCheckpoints with n: %d > %d\n", n, members->checkPoints->size());
exit(1);
}
while (--n >= 0) {
// extract last checkpoint
cp = (*members->checkPoints)[members->checkPoints->size()-1];
// remember the last deleted checkpoint
*members->lastDeletedCheckpoint = cp.second;
members->checkPoints->pop_back();
}
}

extern int ErrorImpl__getNumCheckpoints(threadData_t *threadData)
{
return getMembers(threadData)->checkPoints->size();
}

extern void ErrorImpl__rollBack(threadData_t *threadData,const char* id)
{
Expand Down Expand Up @@ -322,6 +344,21 @@ extern void ErrorImpl__rollBack(threadData_t *threadData,const char* id)
}
}

extern void ErrorImpl__rollbackNumCheckpoints(threadData_t *threadData, int n)
{
errorext_members *members = getMembers(threadData);
if (members->checkPoints->size() < n) {
fprintf(stderr, "ERROREXT: calling ErrorImpl__rollbackNumCheckpoints with n: %d > %d\n", n, members->checkPoints->size());
exit(1);
}
while (--n >= 0) {
while(members->errorMessageQueue->size() > members->checkPoints->back().first && !members->errorMessageQueue->empty()){
pop_message(threadData,true);
}
members->checkPoints->pop_back();
}
}

extern char* ErrorImpl__rollBackAndPrint(threadData_t *threadData,const char* id)
{
errorext_members *members = getMembers(threadData);
Expand Down
2 changes: 2 additions & 0 deletions SimulationRuntime/c/meta/meta_modelica_segv.c
Expand Up @@ -178,6 +178,7 @@ static void* getStackBase() {

void init_metamodelica_segv_handler()
{
#if 0
char *stack = (char*)malloc(SIGSTKSZ);
stack_t ss = {
.ss_size = SIGSTKSZ,
Expand All @@ -191,6 +192,7 @@ void init_metamodelica_segv_handler()
sigfillset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, &default_segv_action);
sigfillset(&segvset);
#endif
}

void mmc_init_stackoverflow(threadData_t *threadData)
Expand Down
4 changes: 2 additions & 2 deletions SimulationRuntime/c/meta/meta_modelica_segv.h
Expand Up @@ -36,8 +36,8 @@
#include <pthread.h>
#include <setjmp.h>
#define MMC_INIT_STACK_OVERFLOW()
#define MMC_TRY_STACK() { jmp_buf *oldMMCJumper = threadData->mmc_jumper; { MMC_TRY_INTERNAL(mmc_stack_overflow_jumper) threadData->mmc_jumper = &new_mmc_jumper; threadData->mmc_stack_overflow_jumper = &new_mmc_jumper;
#define MMC_ELSE_STACK() } else { threadData->mmc_jumper = oldMMCJumper; threadData->mmc_jumper = old_jumper;
#define MMC_TRY_STACK() { jmp_buf *oldMMCJumper = threadData->mmc_jumper; { MMC_TRY_INTERNAL(mmc_stack_overflow_jumper) threadData->mmc_stack_overflow_jumper = &new_mmc_jumper;
#define MMC_ELSE_STACK() } else { threadData->mmc_jumper = oldMMCJumper; threadData->mmc_stack_overflow_jumper = old_jumper;
#define MMC_CATCH_STACK() MMC_CATCH_INTERNAL(mmc_stack_overflow_jumper) } threadData->mmc_jumper = oldMMCJumper; }

void printStacktraceMessages();
Expand Down

0 comments on commit 7f30078

Please sign in to comment.