summaryrefslogtreecommitdiff
path: root/sys/src/cmd/acid
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-02-09 01:37:05 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-02-09 01:37:05 +0100
commit9d8f5a14662f6500c21ac4fa0afd083fc9e2467a (patch)
treedb231af5a5033762b8dbd713de1776839037f53b /sys/src/cmd/acid
parent6b146c70c2863bf1e9d5c4a35cbd8426c5a161e7 (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')
-rw-r--r--sys/src/cmd/acid/acid.h1
-rw-r--r--sys/src/cmd/acid/dbg.y6
-rw-r--r--sys/src/cmd/acid/exec.c27
-rw-r--r--sys/src/cmd/acid/lex.c6
4 files changed, 31 insertions, 9 deletions
diff --git a/sys/src/cmd/acid/acid.h b/sys/src/cmd/acid/acid.h
index 897a0cc50..bd0d6b7cb 100644
--- a/sys/src/cmd/acid/acid.h
+++ b/sys/src/cmd/acid/acid.h
@@ -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);
diff --git a/sys/src/cmd/acid/dbg.y b/sys/src/cmd/acid/dbg.y
index 0bc2a3d74..78dd6105e 100644
--- a/sys/src/cmd/acid/dbg.y
+++ b/sys/src/cmd/acid/dbg.y
@@ -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: ");
}
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");
diff --git a/sys/src/cmd/acid/lex.c b/sys/src/cmd/acid/lex.c
index 0092978fa..5c7ed6c81 100644
--- a/sys/src/cmd/acid/lex.c
+++ b/sys/src/cmd/acid/lex.c
@@ -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;
}