Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[9fans] rc environment variable flush

42 views
Skip to first unread message

cinap_...@gmx.de

unread,
Aug 19, 2013, 3:35:07 PM8/19/13
to
x=foo; @{x=bar}; echo `{cat /env/x}

yields "foo" but

x=foo; echo; @{x=bar}; echo `{cat /env/x}

yields "bar"

the problem is that the environment variables are
only flushed to /env on exec, but not on fork.

in the first example, after executing the
subshell, x is still marked as "modified" by
us and the cat/echo will cause the old value
to be flushed and the changed value from the
subshell be overridden.

havntfork.c does flush the variables on fork tho.

i think it would be more consistent todo this for
havefork.c as well.

is there a good reason not to?

the following patch seems to work fine:

diff -r 5a4a76cd3657 sys/src/cmd/rc/havefork.c
--- a/sys/src/cmd/rc/havefork.c Mon Aug 19 16:07:07 2013 +0200
+++ b/sys/src/cmd/rc/havefork.c Mon Aug 19 21:31:06 2013 +0200
@@ -12,10 +12,12 @@
int null = open("/dev/null", 0);
int pid;
char npid[10];
+
if(null<0){
Xerror("Can't open /dev/null\n");
return;
}
+ Updenv();
switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
case -1:
close(null);
@@ -45,10 +47,12 @@
int lfd = p->code[pc++].i;
int rfd = p->code[pc++].i;
int pfd[2];
+
if(pipe(pfd)<0){
Xerror("can't get pipe");
return;
}
+ Updenv();
switch(forkid = fork()){
case -1:
Xerror("try again");
@@ -91,6 +95,7 @@
Xerror("can't make pipe");
return;
}
+ Updenv();
switch(pid = fork()){
case -1:
Xerror("try again");
@@ -152,6 +157,7 @@
char name[40];
int pfd[2];
int sidefd, mainfd;
+
if(pipe(pfd)<0){
Xerror("can't get pipe");
return;
@@ -164,6 +170,7 @@
sidefd = pfd[PRD];
mainfd = pfd[PWR];
}
+ Updenv();
switch(pid = fork()){
case -1:
Xerror("try again");
@@ -191,6 +198,8 @@
Xsubshell(void)
{
int pid;
+
+ Updenv();
switch(pid = fork()){
case -1:
Xerror("try again");

--
cinap

erik quanstrom

unread,
Aug 19, 2013, 4:24:54 PM8/19/13
to
On Mon Aug 19 15:37:24 EDT 2013, cinap_...@gmx.de wrote:
> x=foo; @{x=bar}; echo `{cat /env/x}
>
> yields "foo" but
>
> x=foo; echo; @{x=bar}; echo `{cat /env/x}
>
> yields "bar"
>
> the problem is that the environment variables are
> only flushed to /env on exec, but not on fork.
>
> in the first example, after executing the
> subshell, x is still marked as "modified" by
> us and the cat/echo will cause the old value
> to be flushed and the changed value from the
> subshell be overridden.
>
> havntfork.c does flush the variables on fork tho.
>
> i think it would be more consistent todo this for
> havefork.c as well.
>
> is there a good reason not to?

here are three reasons. i am not sure if any of them are
good
- it is going to be nearly impossible to
tell if this behavior is depended on somewhere.
- it also potentially has performance implications.
- subshells can also run asynchronous, asynchronously
modifying the environment. don't we still have a race?

- erik

cinap_...@gmx.de

unread,
Aug 19, 2013, 4:53:47 PM8/19/13
to
on races... normal forks will all share the /env environment but
not the in memory variables of rc. so when we would normally fork
whoever does an exec (flush) first will override what the values of the
/env variables are, *independent* of the variables that where
actually modified *in* the process.

when we flush *before* fork, then at least both processes start out
with marked clean in memory variables and the processes will flush
only the things they actually change.

--
cinap

0 new messages