diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-11-22 02:39:57 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-11-22 02:39:57 +0100 |
commit | 98363cb27276b29ff3795d1ef93e4ea2e82e106f (patch) | |
tree | df142a47c3c630e8f9915c15df2a893a37462877 /sys/src/9 | |
parent | 38e1e5272fc9c66a00d702246813135452819ffe (diff) |
devenv: fix ORCLOSE handling
when opening a /env file ORCLOSE, and the process exits, envgrp() would
return nil can crash in envremove() because procexit will have set up->egrp
to nil before calling closefgrp().
the solution is to capture the environment on open, keeping a reference in
Chan.aux, so it doesnt matter on what process the close happens and a
env chan will always refer to its original environment group.
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/port/devenv.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/sys/src/9/port/devenv.c b/sys/src/9/port/devenv.c index 728df1f47..4e12ad514 100644 --- a/sys/src/9/port/devenv.c +++ b/sys/src/9/port/devenv.c @@ -132,8 +132,10 @@ envopen(Chan *c, int omode) runlock(eg); } c->mode = openmode(omode); - c->flag |= COPEN; + incref(eg); + c->aux = eg; c->offset = 0; + c->flag |= COPEN; return c; } @@ -181,7 +183,8 @@ envcreate(Chan *c, char *name, int omode, ulong) wunlock(eg); poperror(); - + incref(eg); + c->aux = eg; c->offset = 0; c->mode = omode; c->flag |= COPEN; @@ -214,13 +217,19 @@ envremove(Chan *c) static void envclose(Chan *c) { - /* - * cclose can't fail, so errors from remove will be ignored. - * since permissions aren't checked, - * envremove can't not remove it if its there. - */ - if(c->flag & CRCLOSE) - envremove(c); + if(c->flag & COPEN){ + /* + * cclose can't fail, so errors from remove will be ignored. + * since permissions aren't checked, + * envremove can't not remove it if its there. + */ + if(c->flag & CRCLOSE && !waserror()){ + envremove(c); + poperror(); + } + closeegrp((Egrp*)c->aux); + c->aux = nil; + } } static long @@ -350,7 +359,7 @@ closeegrp(Egrp *eg) { Evalue *e, *ee; - if(decref(eg) == 0){ + if(decref(eg) == 0 && eg != &confegrp){ e = eg->ent; for(ee = e + eg->nent; e < ee; e++){ free(e->name); |