diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-09 01:37:05 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-09 01:37:05 +0100 |
commit | 9d8f5a14662f6500c21ac4fa0afd083fc9e2467a (patch) | |
tree | db231af5a5033762b8dbd713de1776839037f53b /sys/src/cmd/acid/exec.c | |
parent | 6b146c70c2863bf1e9d5c4a35cbd8426c5a161e7 (diff) |
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.
Diffstat (limited to 'sys/src/cmd/acid/exec.c')
-rw-r--r-- | sys/src/cmd/acid/exec.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/sys/src/cmd/acid/exec.c b/sys/src/cmd/acid/exec.c index 3d9bd590b..09663a15a 100644 --- a/sys/src/cmd/acid/exec.c +++ b/sys/src/cmd/acid/exec.c @@ -57,6 +57,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) { Value *v; @@ -66,7 +92,6 @@ execute(Node *n) Node res, xx; static int stmnt; - gc(); if(gotint) error("interrupted"); |