This is the mail archive of the glibc-bugs@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/863] New: __libc_start_main() resets __environ


The INIT_ARGV_and_ENVIRON macro defined in sysdeps/generic/bp-start.h
(and called from __libc_start_main()) sets the global __environ
pointer.  Unfortunately, this overrides any changes to __environ that
were made by __add_to_environ() in sysdeps/generic/setenv.c.  This
causes problems for dynamically linked libraries whose _init()
function calls setenv(), since the dynamic library initialization
occurs before __libc_start_main() runs.  (Actually, it looks like
__environ may be uninitialized if setenv() is called from a dynamic
library intializer, but I'm not certain.)  This is with glibc source
code version 2.3.3 (unmodified, straigt from the tar file).

Here's an example program which illustrates this behavior:

-- envlib.cc:

#include <stdlib.h>

struct PreEnvlibSetter {
  PreEnvlibSetter() { setenv("ENVLIB_PRE", "1", 1); }
};
static PreEnvlibSetter dummy1;    // gets called before main() is called

struct PostEnvlibSetter {
  PostEnvlibSetter() { setenv("ENVLIB_POST", "1", 1); }
};
void EnvlibSetter() {
  PostEnvlibSetter dummy2;        // gets called after main() is called
}

-- env.cc:

#include <stdio.h>
#include <stdlib.h>

struct PreEnvSetter {
  PreEnvSetter() { setenv("ENV_PRE", "1", 1); }
};
static PreEnvSetter dummy3;    // gets called before main() is called

struct PostEnvSetter {
  PostEnvSetter() { setenv("ENV_POST", "1", 1); }
};
void EnvSetter() {             // gets called after main() is called
  PostEnvSetter dummy4;
}

void EnvlibSetter();

int main(int argc, char** argv) {
  EnvlibSetter();
  EnvSetter();

  printf("envlib-pre: %s\nenvlib-post: %s\nenv-pre: %s\nenv-post: %s\n",
         getenv("ENVLIB_PRE"), getenv("ENVLIB_POST"),
         getenv("ENV_PRE"), getenv("ENV_POST"));
  return 0;
}

--

When I compile in one unit, everything works as I'd expect:
% gcc env.cc envlib.cc -lstdc++
% ./a.out
envlib-pre: 1
envlib-post: 1
env-pre: 1
env-post: 1

But when I put envlib into a shared library, ENVLIB_PRE doesn't "stick":
% gcc -shared envlib.cc -oenvlib.so
% gcc env.cc `pwd`/envlib.so -lstdc++
% ./a.out
envlib-pre: (null)
envlib-post: 1
env-pre: 1
env-post: 1

Also:
% gcc --version
gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
Copyright (C) 2002 Free Software Foundation, Inc.

craig

-- 
           Summary: __libc_start_main() resets __environ
           Product: glibc
           Version: 2.3.3
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: csilvers at google dot com
                CC: glibc-bugs at sources dot redhat dot com
 GCC build triplet: any
  GCC host triplet: any
GCC target triplet: any


http://sources.redhat.com/bugzilla/show_bug.cgi?id=863

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]