acid: fix memory corruption due to gc

we cannot call gc() in execute() because it will gc
anonyous intermediate results which happens when we
construct a list and the elements are calculated by
calling a function thru ocall() which calls execute().

also, the _thiscmd symbol; which is used to keep
a reference to a statement so it wont get garbage
collected; does not work as yyparse() is recursive
(include statements).

we add execrec() function which *only* gets called from
yyparse() when evaluating a statement. it will
keep a stack on the _thiscmd symbol handling the yyparse()
recursion.

we also only call gc() in execrec() before calling
execute(). so execute() will never gc() while evaluating
a statement which prevents the intermediate results
from getting collected.
This commit is contained in:
cinap_lenrek 2014-02-09 01:37:05 +01:00
parent 6b146c70c2
commit 9d8f5a1466
4 changed files with 31 additions and 9 deletions

View file

@ -190,6 +190,7 @@ void dostop(int);
Lsym* enter(char*, int);
void error(char*, ...);
void execute(Node*);
void execrec(Node*);
void fatal(char*, ...);
void flatten(Node**, Node*);
void gc(void);

View file

@ -50,11 +50,7 @@ prog :
bigstmnt : stmnt
{
/* make stmnt a root so it isn't collected! */
mkvar("_thiscmd")->proc = $1;
execute($1);
mkvar("_thiscmd")->proc = nil;
gc();
execrec($1);
if(interactive)
Bprint(bout, "acid: ");
}

View file

@ -56,6 +56,32 @@ unwind(void)
}
}
void
execrec(Node *n)
{
Value *v;
Lsym *s;
/* make node a root so it isn't collected! */
s = mkvar("_thiscmd");
v = gmalloc(sizeof(Value));
memset(v, 0, sizeof(Value));
v->type = TCODE;
v->cc = n;
v->pop = s->v;
s->v = v;
s->proc = n;
gc();
execute(n);
s->proc = s->v->cc;
s->v = v->pop;
free(v);
}
void
execute(Node *n)
{
@ -66,7 +92,6 @@ execute(Node *n)
Node res, xx;
static int stmnt;
gc();
if(gotint)
error("interrupted");

View file

@ -569,11 +569,11 @@ enter(char *name, int t)
s->lexval = t;
v = gmalloc(sizeof(Value));
s->v = v;
memset(v, 0, sizeof(Value));
v->fmt = 'X';
v->type = TINT;
memset(v, 0, sizeof(Value));
s->v = v;
return s;
}