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;
}

Reply via email to