On Thu, Feb 14, 2013 at 4:18 PM, Paul Eggert <egg...@cs.ucla.edu> wrote:
> On 02/14/13 10:15, Michael Goffioul wrote: > > > > Yes, it fixes the problem. > > Thanks for checking. I installed that into the gnulib master. > Thanks. However I made some further tests and found out that gnulib's implementation of putenv suffers from an annoying problem: changes in the environment are not inherited by child processes, except those that are made through native _putenv. The problem is that the "environ" variable is just a mirror of the environment that is manipulated through GetEnvironmentVariable and SetEnvironmentVariable. Manipulating the "environ" variable directly has no effect at the OS level and will only affect the current process (only calls to _putenv will actually propagate the changes through Win32 API). Child processes will not see the modified environment. Moreover even in the current process, I believe the values returned by GetEnvironmentVariable and "environ" (or getenv) will not be in sync. I made tests with MSVC, but I believe the problem also occurs with MinGW. The attached source is an alteration of the test code in putenv.m4 to illustrate the problem, I compiled and linked it with gnulib's putenv.c and malloc.c. When being run, the output is: variable creation internal: val external: val variable change with gnulib::putenv internal: newval external: val variable change with _putenv internal: newval external: newval Note that this problem is not due to Paul's changes. These actually made things a bit better. Before that change, variable creations and modifications were not propagated to Win32 API. After the change, only variable modifications are not propagated. I guess the only solution to this problem is to always _putenv and not manipulate "environ" directly. Michael.
#include <stdlib.h> #include <stdio.h> int main (int argc, char **argv) { if (putenv ("CONFTEST_putenv=val")) return 1; printf ("variable creation\n"); printf ("internal: %s\n", getenv ("CONFTEST_putenv")); system ("echo external: %CONFTEST_putenv%"); if (putenv ("CONFTEST_putenv=newval")) return 4; printf ("variable change with gnulib::putenv\n"); printf ("internal: %s\n", getenv ("CONFTEST_putenv")); system ("echo external: %CONFTEST_putenv%"); if (_putenv ("CONFTEST_putenv=newval")) return 5; printf ("variable change with _putenv\n"); printf ("internal: %s\n", getenv ("CONFTEST_putenv")); system ("echo external: %CONFTEST_putenv%"); /* Try to remove it. */ if (putenv ("CONFTEST_putenv")) return 2; /* Make sure it was deleted. */ if (getenv ("CONFTEST_putenv") != 0) return 3; return 0; }