diff options
-rw-r--r-- | libiberty/ChangeLog | 4 | ||||
-rw-r--r-- | libiberty/pex-unix.c | 21 |
2 files changed, 24 insertions, 1 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index ddabcd3..f8ba8f7 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,7 @@ +2009-12-07 Doug Evans <dje@google.com> + + * pex-unix.c (pex_unix_exec_child): Save/restore environ. + 2009-11-26 Ben Elliston <bje@au.ibm.com> * configure.ac (AC_CHECK_FUNCS): Sort into alphabetic order. diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index 4428f60..85733a6 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -400,6 +400,12 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, volatile int sleep_interval; volatile int retries; + /* We vfork and then set environ in the child before calling execvp. + This clobbers the parent's environ so we need to restore it. + It would be nice to use one of the exec* functions that takes an + environment as a parameter, but that may have portability issues. */ + char **save_environ = environ; + sleep_interval = 1; pid = -1; for (retries = 0; retries < 4; ++retries) @@ -453,7 +459,12 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, } if (env) - environ = (char**) env; + { + /* NOTE: In a standard vfork implementation this clobbers the + parent's copy of environ "too" (in reality there's only one copy). + This is ok as we restore it below. */ + environ = (char**) env; + } if ((flags & PEX_SEARCH) != 0) { @@ -471,6 +482,14 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, default: /* Parent process. */ + + /* Restore environ. + Note that the parent either doesn't run until the child execs/exits + (standard vfork behaviour), or if it does run then vfork is behaving + more like fork. In either case we needn't worry about clobbering + the child's copy of environ. */ + environ = save_environ; + if (in != STDIN_FILE_NO) { if (close (in) < 0) |