Changeset: 215f07083cd7 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=215f07083cd7
Modified Files:
monetdb5/mal/mal_interpreter.mx
Branch: default
Log Message:
Protect against concurrent exceptions
If multiple parallel blocks access the exception variables
and perform GDKfree on old messages, then we may enter a
case that one thread attempts a second free.
Simple lock-based protection is the first line of defense.
diffs (125 lines):
diff --git a/monetdb5/mal/mal_interpreter.mx b/monetdb5/mal/mal_interpreter.mx
--- a/monetdb5/mal/mal_interpreter.mx
+++ b/monetdb5/mal/mal_interpreter.mx
@@ -262,14 +262,15 @@
if (mb->vtop > stk->stksize)
showScriptException(mb, 0, MAL, "stack too small\n");
pci = pcicaller;
+ @:initStack(env->stkbot)@
} else {
- newStack(stk, mb->vsize);
- stk->stktop = mb->vtop;
- stk->stksize = mb->vsize;
+ stk= prepareMALstack(mb, mb->vsize);
+ if (stk == 0)
+ throw(MAL,"mal.interpreter",MAL_STACK_FAIL);
stk->blk = mb;
stk->cmd = cntxt->itrace; /* set debug mode */
+ /*safeguardStack*/
if (env) {
- /*safeguardStack*/
stk->stkdepth = stk->stksize + env->stkdepth;
stk->calldepth = env->calldepth + 1;
if (stk->calldepth > 256)
@@ -278,7 +279,6 @@
/* we are running low on stack space */
throw(MAL, "mal.interpreter", MAL_STACK_FAIL);
}
- }
@-
An optimization is to copy all constant variables used in functions immediately
onto the value stack. Then we do not have to check for their location
@@ -286,12 +286,6 @@
constants are referenced in a function (a gain on tst400a of 20% has been
observed due the small size of the function).
@c
- if (env && mbcaller) {
- @:initStack(0)@
- } else if (env && env->stkbot) {
- @:initStack(env->stkbot)@
- } else {
- @:initStack(0)@
}
if (env && mbcaller) {
@@ -381,7 +375,7 @@
MalStkPtr stk = NULL;
str ret = MAL_SUCCEED;
int i;
- ValPtr lhs, rhs;
+ ValPtr lhs;
InstrPtr pci = getInstrPtr(mb, 0);
@:performanceVariables@
@@ -398,13 +392,8 @@
all arguments and return values.
@c
if (*env == NULL) {
- stk = newGlobalStack(mb->vsize);
- memset((char *)stk, 0, stackSize(mb->vtop));
- stk->stktop = mb->vtop;
- stk->stksize = mb->vsize;
- stk->blk = mb;
+ stk = prepareMALstack(mb, mb->vsize);
stk->up = 0;
- @:initStack(0)@
*env = stk;
} else stk = *env;
assert(stk);
@@ -2035,10 +2024,37 @@
@-
@= functioncall
-{
+{ MalStkPtr nstk;
+ InstrPtr q;
+ int ii, arg;
+
stk->pcup = stkpc;
@:safeTarget(@1)@
- ret = runMAL(cntxt, pci->blk, 1, mb, stk, pci);
+ nstk = prepareMALstack(pci->blk, pci->blk->vsize);
+ if (nstk == 0)
+ throw(MAL,"mal.interpreter",MAL_STACK_FAIL);
+
+ /*safeguardStack*/
+ nstk->stkdepth = nstk->stksize + stk->stkdepth;
+ nstk->calldepth = stk->calldepth + 1;
+ if (nstk->calldepth > 256)
+ throw(MAL, "mal.interpreter", MAL_CALLDEPTH_FAIL);
+ if ((unsigned)nstk->stkdepth > THREAD_STACK_SIZE / sizeof(mb->var[0]) /
4 && THRhighwater())
+ /* we are running low on stack space */
+ throw(MAL, "mal.interpreter", MAL_STACK_FAIL);
+
+ /* copy arguments onto destination stack */
+ q= getInstrPtr(pci->blk,0);
+ arg = q->retc;
+ for (ii = pci->retc; ii < pci->argc; ii++,arg++) {
+ lhs = &nstk->stk[q->argv[arg]];
+ rhs = &stk->stk[pci->argv[ii]];
+ VALcopy(lhs, rhs);
+ if (lhs->vtype == TYPE_bat)
+ BBPincref(lhs->val.bval, TRUE);
+ }
+ ret = runMALsequence(cntxt, pci->blk, 1, pci->blk->stop, nstk, stk,
pci);
+ GDKfree(nstk);
@:restoreTarget(@1,@3)@
@:exceptionHndlr(@1,@2,@3)@
@:timingHndlr(@1)@
@@ -2282,6 +2298,8 @@
}
/* assure correct variable type */
if (getVarType(mb, exceptionVar) == TYPE_str) {
+ /* watch out for concurrent access */
+ mal_set_lock(mal_contextLock, "exception handler");
v = &stk->stk[exceptionVar];
if (v->val.sval)
FREE_EXCEPTION(v->val.sval); /* old exception*/
@@ -2289,6 +2307,7 @@
v->val.sval = ret;
v->len = (int)strlen(v->val.sval);
ret = 0;
+ mal_unset_lock(mal_contextLock, "exception handler");
} else {
mnstr_printf(cntxt->fdout, "%s", ret);
FREE_EXCEPTION(ret);
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list