shithub: riscv

Download patch

ref: 98363cb27276b29ff3795d1ef93e4ea2e82e106f
parent: 38e1e5272fc9c66a00d702246813135452819ffe
author: cinap_lenrek <[email protected]>
date: Sat Nov 21 21:39:57 EST 2015

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.

--- a/sys/src/9/port/devenv.c
+++ b/sys/src/9/port/devenv.c
@@ -132,8 +132,10 @@
 			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 @@
 
 	wunlock(eg);
 	poperror();
-
+	incref(eg);
+	c->aux = eg;
 	c->offset = 0;
 	c->mode = omode;
 	c->flag |= COPEN;
@@ -214,13 +217,19 @@
 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 @@
 {
 	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);