Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 846ccc5

Browse files
sjoelundOpenModelica-Hudson
authored andcommitted
Catch out of memory errors
Also added an API call to limit the maximum GC heap. This is useful when you are using a ulimit on vmem since the OS simply kills the process instead of making malloc calls return NULL. The eval loop will now catch out of memory and stack overflow and continue with the next command. This is annoying for mos-scripts but is necessary to make OMPython not simply crash (we want to get the error-message through getErrorString(), and hopefully there is enough memory to get the string after collecting some garbage). Belonging to [master]: - #2210 - OpenModelica/OpenModelica-testsuite#855
1 parent 30a4db0 commit 846ccc5

22 files changed

+211
-77
lines changed

Compiler/FrontEnd/Inst.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3136,7 +3136,7 @@ algorithm
31363136
(outCache, outEnv, outIH, outStore, DAE.DAE(outDae), outSets, outState, outVars, outGraph, outFieldDomOpt) :=
31373137
instElement(outCache, outEnv, outIH, outStore, inMod, inPrefix, outState, elt, inInstDims,
31383138
inImplicit, inCallingScope, outGraph, inSets);
3139-
Error.updateCurrentComponent(Prefix.NOPRE(), "", Absyn.dummyInfo, PrefixUtil.identAndPrefixToPath);
3139+
Error.clearCurrentComponent();
31403140
ErrorExt.delCheckpoint("instElement2");
31413141
else // Instantiation failed, fail or skip the element depending on inStopOnError.
31423142
if inStopOnError then

Compiler/FrontEnd/InstVar.mo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,9 +604,9 @@ algorithm
604604
outCache := InstFunction.addRecordConstructorFunction(outCache, inEnv,
605605
Types.arrayElementType(outType), SCode.elementInfo(inClass));
606606

607-
Error.updateCurrentComponent(Prefix.NOPRE(), "", Absyn.dummyInfo, PrefixUtil.identAndPrefixToPath);
607+
Error.clearCurrentComponent();
608608
else
609-
Error.updateCurrentComponent(Prefix.NOPRE(), "", Absyn.dummyInfo, PrefixUtil.identAndPrefixToPath);
609+
Error.clearCurrentComponent();
610610
fail();
611611
end try;
612612
end instVar_dispatch;

Compiler/FrontEnd/ModelicaBuiltin.mo

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3869,6 +3869,16 @@ annotation(
38693869
</html>"));
38703870
end GC_expand_hp;
38713871

3872+
function GC_set_max_heap_size
3873+
input Integer size;
3874+
output Boolean success;
3875+
external "builtin";
3876+
annotation(
3877+
Documentation(info="<html>
3878+
<p>Forces the GC to limit the maximum heap size.</p>
3879+
</html>"));
3880+
end GC_set_max_heap_size;
3881+
38723882
function checkInterfaceOfPackages
38733883
input TypeName cl;
38743884
input String dependencyMatrix[:,:];

Compiler/Script/CevalScript.mo

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,11 @@ algorithm
677677
b = GC.expandHeap(i);
678678
then (cache,Values.BOOL(b));
679679

680+
case (cache,_,"GC_set_max_heap_size",{Values.INTEGER(i)},_)
681+
equation
682+
GC.setMaxHeapSize(i);
683+
then (cache,Values.BOOL(true));
684+
680685
case (cache,_,"clear",{},_)
681686
algorithm
682687
SymbolTable.reset();

Compiler/Script/Interactive.mo

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import ExpressionSimplify;
8080
import FBuiltin;
8181
import Flags;
8282
import FGraph;
83+
import GC;
8384
import GlobalScriptDump;
8485
import GlobalScriptUtil;
8586
import InnerOuter;
@@ -94,6 +95,7 @@ import Parser;
9495
import Prefix;
9596
import Print;
9697
import Refactor;
98+
import StackOverflow;
9799
import Static;
98100
import StaticScript;
99101
import StringUtil;
@@ -322,19 +324,22 @@ public function evaluate2
322324
"Helper function to evaluate."
323325
input GlobalScript.Statements inStatements;
324326
output String outString;
327+
protected
328+
GlobalScript.Statement stmt;
329+
String str, str_1;
325330
algorithm
326-
outString := matchcontinue inStatements
331+
GlobalScript.ISTMTS(interactiveStmtLst = {stmt}) := inStatements;
332+
try /* Stack overflow */
333+
outString := matchcontinue stmt
327334
local
328-
String str,str_1;
329-
GlobalScript.Statements stmts;
330335
Absyn.AlgorithmItem algitem;
331336
Boolean outres;
332337
Absyn.Exp exp;
333338
Boolean partialInst, gen, evalfunc, keepArrays;
334339
SourceInfo info;
335340

336341
// evaluate graphical API
337-
case (stmts as GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(exp = Absyn.CALL())}))
342+
case GlobalScript.IEXP(exp = Absyn.CALL())
338343
equation
339344
// adrpo: always evaluate the graphicalAPI with these options so instantiation is faster!
340345
partialInst = System.getPartialInstantiation();
@@ -344,26 +349,41 @@ algorithm
344349
keepArrays = Flags.getConfigBool(Flags.KEEP_ARRAYS);
345350
Flags.setConfigBool(Flags.KEEP_ARRAYS, false);
346351
Inst.initInstHashTable();
347-
str = evaluateGraphicalApi(stmts, partialInst, gen, evalfunc, keepArrays);
352+
str = evaluateGraphicalApi(stmt, partialInst, gen, evalfunc, keepArrays);
348353
str_1 = stringAppend(str, "\n");
349354
then str_1;
350355

351356
// Evaluate algorithm statements in evaluateAlgStmt()
352-
case GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IALG(algItem = (algitem as Absyn.ALGORITHMITEM()))})
357+
case GlobalScript.IALG(algItem = (algitem as Absyn.ALGORITHMITEM()))
353358
equation
354359
Inst.initInstHashTable();
355360
str = evaluateAlgStmt(algitem);
356361
str_1 = stringAppend(str, "\n");
357362
then str_1;
358363

359364
// Evaluate expressions in evaluate_exprToStr()
360-
case GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(exp = exp, info = info)})
365+
case GlobalScript.IEXP(exp = exp, info = info)
361366
equation
362367
Inst.initInstHashTable();
363368
str = evaluateExprToStr(exp, info);
364369
str_1 = stringAppend(str, "\n");
365370
then str_1;
366371
end matchcontinue;
372+
else
373+
str := "";
374+
str_1 := "";
375+
GC.gcollect();
376+
str := StackOverflow.getReadableMessage();
377+
if Config.getRunningTestsuite() then
378+
/* It's useful to print the name of the component we failed on.
379+
* But we crash in different places, so for the testsuite we skip this.
380+
*/
381+
Error.clearCurrentComponent();
382+
end if;
383+
Error.addMessage(Error.STACK_OVERFLOW_DETAILED, {GlobalScriptDump.printIstmtStr(stmt), str});
384+
Error.clearCurrentComponent();
385+
outString := "\n";
386+
end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
367387
end evaluate2;
368388

369389
protected function evaluateAlgStmt
@@ -839,47 +859,43 @@ end getTypeOfVariable;
839859

840860
protected function getApiFunctionNameInfo
841861
"Returns the name of the called API function."
842-
input GlobalScript.Statements inStmts;
862+
input GlobalScript.Statement inStmt;
843863
output String outName;
844864
output SourceInfo outInfo;
845865
algorithm
846-
GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(
866+
GlobalScript.IEXP(
847867
exp = Absyn.CALL(function_ = Absyn.CREF_IDENT(name = outName)),
848868
info = outInfo
849-
)}) := inStmts;
869+
) := inStmt;
850870
end getApiFunctionNameInfo;
851871

852872
protected function getApiFunctionArgs
853873
"Returns a list of arguments to the function in the interactive statement list."
854-
input GlobalScript.Statements inStmts;
874+
input GlobalScript.Statement inStmt;
855875
output list<Absyn.Exp> outArgs;
856876
algorithm
857-
outArgs := match(inStmts)
877+
outArgs := match(inStmt)
858878
local
859879
list<Absyn.Exp> args;
860880

861-
case (GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(exp = Absyn.CALL(functionArgs =
862-
Absyn.FUNCTIONARGS(args = args)))})) then args;
881+
case GlobalScript.IEXP(exp = Absyn.CALL(functionArgs =
882+
Absyn.FUNCTIONARGS(args = args))) then args;
863883
else {};
864884
end match;
865885
end getApiFunctionArgs;
866886

867887
protected function getApiFunctionNamedArgs
868888
"Returns a list of named arguments to the function in the interactive statement list."
869-
input GlobalScript.Statements inStmts;
889+
input GlobalScript.Statement inStmt;
870890
output list<Absyn.NamedArg> outArgs;
871891
algorithm
872-
outArgs := match(inStmts)
873-
local list<Absyn.NamedArg> args;
874-
case (GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(exp = Absyn.CALL(functionArgs =
875-
Absyn.FUNCTIONARGS(argNames = args)))})) then args;
876-
end match;
892+
GlobalScript.IEXP(exp = Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(argNames = outArgs))) := inStmt;
877893
end getApiFunctionNamedArgs;
878894

879895
protected function evaluateGraphicalApi
880896
"Evaluating graphical api.
881897
NOTE: the graphical API is always evaluated with checkModel ON and -d=nogen,noevalfunc ON"
882-
input GlobalScript.Statements inStatements;
898+
input GlobalScript.Statement inStatement;
883899
input Boolean isPartialInst;
884900
input Boolean flagGen;
885901
input Boolean flagEvalFunc;
@@ -891,7 +907,7 @@ protected
891907
Boolean failed = false;
892908
algorithm
893909
try
894-
outResult := evaluateGraphicalApi_dispatch(inStatements);
910+
outResult := evaluateGraphicalApi_dispatch(inStatement);
895911
else
896912
failed := true;
897913
end try;
@@ -907,7 +923,7 @@ end evaluateGraphicalApi;
907923

908924
protected function evaluateGraphicalApi_dispatch
909925
"This function evaluates all primitives in the graphical api."
910-
input GlobalScript.Statements inStatements;
926+
input GlobalScript.Statement inStatement;
911927
output String outResult;
912928
protected
913929
String fn_name, name;
@@ -928,9 +944,9 @@ protected
928944
Absyn.Exp exp;
929945
list<Absyn.Exp> dimensions;
930946
algorithm
931-
fn_name := getApiFunctionNameInfo(inStatements);
947+
fn_name := getApiFunctionNameInfo(inStatement);
932948
p := SymbolTable.getAbsyn();
933-
args := getApiFunctionArgs(inStatements);
949+
args := getApiFunctionArgs(inStatement);
934950

935951
outResult := match(fn_name)
936952
case "setComponentModifierValue"
@@ -990,7 +1006,7 @@ algorithm
9901006
{Absyn.CREF(componentRef = Absyn.CREF_IDENT(name = name)),
9911007
Absyn.CREF(componentRef = tp),
9921008
Absyn.CREF(componentRef = model_)} := args;
993-
nargs := getApiFunctionNamedArgs(inStatements);
1009+
nargs := getApiFunctionNamedArgs(inStatement);
9941010
p := addComponent(name, tp, model_, nargs, p);
9951011
Print.clearBuf();
9961012
then
@@ -1001,7 +1017,7 @@ algorithm
10011017
{Absyn.CREF(componentRef = Absyn.CREF_IDENT(name = name)),
10021018
Absyn.CREF(componentRef = tp),
10031019
Absyn.CREF(componentRef = model_)} := args;
1004-
nargs := getApiFunctionNamedArgs(inStatements);
1020+
nargs := getApiFunctionNamedArgs(inStatement);
10051021
(p, outResult) := updateComponent(name, tp, model_, nargs, p);
10061022
then
10071023
outResult;
@@ -1010,7 +1026,7 @@ algorithm
10101026
algorithm
10111027
{Absyn.CREF(componentRef = Absyn.CREF_IDENT(name = name)),
10121028
Absyn.CREF(componentRef = model_)} := args;
1013-
{} := getApiFunctionNamedArgs(inStatements);
1029+
{} := getApiFunctionNamedArgs(inStatement);
10141030
p := deleteOrUpdateComponent(name, model_, p, NONE());
10151031
Print.clearBuf();
10161032
then "true";
@@ -1033,7 +1049,7 @@ algorithm
10331049
case "getComponents"
10341050
algorithm
10351051
{Absyn.CREF(componentRef = cr)} := args;
1036-
nargs := getApiFunctionNamedArgs(inStatements);
1052+
nargs := getApiFunctionNamedArgs(inStatement);
10371053
outResult := getComponents(cr, useQuotes(nargs));
10381054
then
10391055
outResult;
@@ -1102,7 +1118,7 @@ algorithm
11021118
{Absyn.CREF(componentRef = cr1),
11031119
Absyn.CREF(componentRef = cr2),
11041120
Absyn.CREF(componentRef = cr)} := args;
1105-
nargs := getApiFunctionNamedArgs(inStatements);
1121+
nargs := getApiFunctionNamedArgs(inStatement);
11061122
(outResult, p) := addConnection(cr, cr1, cr2, nargs, p);
11071123
then
11081124
outResult;
@@ -1121,7 +1137,7 @@ algorithm
11211137
{Absyn.CREF(componentRef = cr1),
11221138
Absyn.CREF(componentRef = cr2),
11231139
Absyn.CREF(componentRef = cr)} := args;
1124-
nargs := getApiFunctionNamedArgs(inStatements);
1140+
nargs := getApiFunctionNamedArgs(inStatement);
11251141
(_, p) := deleteConnection(cr, cr1, cr2, p);
11261142
(outResult, p) := addConnection(cr, cr1, cr2, nargs, p);
11271143
then
@@ -1374,7 +1390,7 @@ algorithm
13741390
case "getExtendsModifierNames"
13751391
algorithm
13761392
{Absyn.CREF(componentRef = class_), Absyn.CREF(componentRef = cr)} := args;
1377-
nargs := getApiFunctionNamedArgs(inStatements);
1393+
nargs := getApiFunctionNamedArgs(inStatement);
13781394
then
13791395
getExtendsModifierNames(class_, cr, useQuotes(nargs), p);
13801396

@@ -1476,7 +1492,7 @@ algorithm
14761492
case "getLocalVariables"
14771493
algorithm
14781494
{Absyn.CREF(componentRef = cr)} := args;
1479-
nargs := getApiFunctionNamedArgs(inStatements);
1495+
nargs := getApiFunctionNamedArgs(inStatement);
14801496
path := Absyn.crefToPath(cr);
14811497
cls := getPathedClassInProgram(path, p);
14821498
env := SymbolTable.buildEnv();

Compiler/Util/Error.mo

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,8 @@ public constant Message MOVING_PARAMETER_BINDING_TO_INITIAL_EQ_SECTION = MESSAGE
933933
Util.gettext("Moving binding to initial equation section and setting fixed attribute of %s to false."));
934934
public constant Message MIXED_DETERMINED = MESSAGE(583, SYMBOLIC(), ERROR(),
935935
Util.gettext("The given system is mixed-determined. [index > %s]\nPlease checkout the option \"--maxMixedDeterminedIndex\"."));
936+
public constant Message STACK_OVERFLOW_DETAILED = MESSAGE(584, SCRIPTING(), ERROR(),
937+
Util.gettext("Stack overflow occurred while evaluating %s:\n%s"));
936938

937939
public constant Message MATCH_SHADOWING = MESSAGE(5001, TRANSLATION(), ERROR(),
938940
Util.gettext("Local variable '%s' shadows another variable."));
@@ -1069,7 +1071,19 @@ public constant Message CONFLICTING_ALIAS_SET = MESSAGE(7017, SYMBOLIC(), WARNIN
10691071
public constant Message ENCRYPTION_NOT_SUPPORTED = MESSAGE(7018, SCRIPTING(), ERROR(),
10701072
Util.gettext("File not Found: %s. Compile OpenModelica with Encryption support."));
10711073

1072-
protected import ErrorExt;
1074+
protected
1075+
1076+
import ErrorExt;
1077+
constant SourceInfo dummyInfo = SOURCEINFO("",false,0,0,0,0,0.0);
1078+
1079+
public function clearCurrentComponent
1080+
protected function dummy
1081+
input output String str;
1082+
input Integer i;
1083+
end dummy;
1084+
algorithm
1085+
updateCurrentComponent(0, "", dummyInfo, dummy);
1086+
end clearCurrentComponent;
10731087

10741088
public function updateCurrentComponent<T> "Function: updateCurrentComponent
10751089
This function takes a String and set the global var to

Compiler/Util/GC.mo

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ function setForceUnmapOnGcollect
9090
external "C" GC_set_force_unmap_on_gcollect(forceUnmap) annotation(Library = {"omcgc"});
9191
end setForceUnmapOnGcollect;
9292

93+
function setMaxHeapSize
94+
input Real sz "To avoid the 32-bit signed limit on sizes";
95+
external "C" GC_set_max_heap_size_dbl(sz) annotation(Include="#define GC_set_max_heap_size_dbl(sz) omc_GC_set_max_heap_size((size_t)sz)",Library = {"omcgc"});
96+
end setMaxHeapSize;
97+
9398
uniontype ProfStats "TODO: Support regular records in the bootstrapped compiler to avoid allocation to return the stats in the GC..."
9499
record PROFSTATS
95100
Integer heapsize_full, free_bytes_full, unmapped_bytes, bytes_allocd_since_gc, allocd_bytes_before_gc, non_gc_bytes, gc_no, markers_m1, bytes_reclaimed_since_gc, reclaimed_bytes_before_gc;

Compiler/Util/StackOverflow.mo

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,16 @@ function generateReadableMessage
9393
output String str;
9494
algorithm
9595
StackOverflow.setStacktraceMessages(numSkip, numFrames);
96-
str := stringDelimitList(StackOverflow.readableStacktraceMessages(),delimiter);
96+
str := getReadableMessage(delimiter=delimiter);
9797
end generateReadableMessage;
9898

99+
function getReadableMessage
100+
input String delimiter="\n";
101+
output String str;
102+
algorithm
103+
str := stringDelimitList(StackOverflow.readableStacktraceMessages(),delimiter);
104+
end getReadableMessage;
105+
99106
function readableStacktraceMessages
100107
output list<String> symbols = {};
101108
protected

Compiler/runtime/Error_omc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ void Error_setShowErrorMessages(threadData_t *threadData,int show)
109109
static void omc_assert_compiler_common(threadData_t *threadData,ErrorLevel severity, FILE_INFO info, const char *msg, va_list args)
110110
{
111111
ErrorMessage::TokenList tokens;
112-
char *str;
112+
const char *str;
113113
GC_vasprintf(&str, msg, args);
114114
add_source_message(threadData, 0, ErrorType_runtime, severity, str, tokens, info.lineStart, info.colStart, info.lineEnd, info.colEnd, info.readonly, info.filename);
115115
}

Compiler/runtime/SimulationResults.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,10 @@ int SimulationResults_filterSimulationResults(const char *inFile, const char *ou
624624
}
625625
}
626626
msg[4] = inFile;
627-
GC_asprintf((char**)msg+3, "%d", simresglob.matReader.nrows);
628-
GC_asprintf((char**)msg+2, "%d", numberOfIntervals);
629-
GC_asprintf((char**)msg+1, "%d", nevents);
630-
GC_asprintf((char**)msg+0, "%d", neventpoints);
627+
GC_asprintf(msg+3, "%d", simresglob.matReader.nrows);
628+
GC_asprintf(msg+2, "%d", numberOfIntervals);
629+
GC_asprintf(msg+1, "%d", nevents);
630+
GC_asprintf(msg+0, "%d", neventpoints);
631631
c_add_message(NULL,-1, ErrorType_scripting, ErrorLevel_notification, gettext("Resampling %s from %s points to %s points, removing %s events stored in %s points.\n"), msg, 5);
632632
}
633633

@@ -650,8 +650,8 @@ int SimulationResults_filterSimulationResults(const char *inFile, const char *ou
650650
var.index=indexesToOutput[i];
651651
if (omc_matlab4_val(vals+j, &simresglob.matReader, &var, t)) {
652652
msg[2] = inFile;
653-
GC_asprintf((char**)msg+1, "%d", indexesToOutput[i]);
654-
GC_asprintf((char**)msg+0, "%.15g", t);
653+
GC_asprintf(msg+1, "%d", indexesToOutput[i]);
654+
GC_asprintf(msg+0, "%.15g", t);
655655
c_add_message(NULL,-1, ErrorType_scripting, ErrorLevel_error, gettext("Resampling %s failed to get variable %s at time %s.\n"), msg, 3);
656656
return 0;
657657
}

0 commit comments

Comments
 (0)