Re: Concurrent usage of glibc 2.2.4 and 2.3.2

From: Myself (pardillaco_at_yahoo.com)
Date: 04/11/04


Date: 10 Apr 2004 18:14:06 -0700

Hi,

First at all, thanks John for your help. I haven't still
managed to make my app work, but I managed to simplify the
problem, and (hopefully) make it repeatable.

John Reiser <jreiser@BitWagon.com> wrote in message news:<c4s42s0c8p@enews2.newsguy.com>...
> ...
> You must invoke the corresponding version of ld-linux.so.2 whenever
> you use a different libc.so.6:
> /lib/ld-2.2.4.so --library-path <path> my_app <args>
> where libc-2.2.4.so is found in <path>, etc. The typical way to do this
> is to add another level of indirection by making my_app a script:
> #!/bin/sh
> # perhaps could use /usr/lib/env as light-weight shell
> exec /lib/ld-2.2.4.so --library_path <path> my_lib/my_app "$@"
> where <path> overrides LD_LIBRARY_PATH and any other attempt to set
> a path for ld.so. If the parent checks not only for executable my_app
> but also for ELF, then you must make an ELF version of such a script.
>
I'm still with the same problem. First, I realized that adding a
--library-path option to the RTL does not affect the LD_LIBRARY_PATH
environment variable.

I wrote the following program (fork.c). The parent process forks a
child process, which execve's /bin/ls (that's how Communicator 4.8
fires the dns helper process). Before the fork, the parent process
prints the LD_LIBRARY_PATH variable it will call the child, which
will be the same /bin/ls is execve'd with.

fork.c

------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

extern char **environ;

int main()
{
  int i;
  int fkid;

  for (i = 0; environ[i] != NULL; i++)
    if (strncmp (environ[i], "LD_LIBRARY_PATH", 15) == 0)
      printf ("[%i] environ[%i] = %s\n", getpid(), i, environ[i]);

  printf ("[%i] fork()\n", getpid());
  fkid = fork();

  if (fkid < 0) {
    fprintf(stderr, "error: fork returned -1 (%s)", strerror(errno));
    exit(1);

  } else if (fkid == 0) {
    // the child
    char* nargv[4];
    nargv[0] = (char *) malloc (10 * sizeof(char));
    strcpy (nargv[0], "ls");
    nargv[1] = (char *) malloc (10 * sizeof(char));
    strcpy (nargv[1], "-Flags");
    nargv[2] = (char *) malloc (10 * sizeof(char));
    strcpy (nargv[2], "/tmp/k");
    nargv[3] = NULL;

    printf ("[%i] execve(\"/bin/ls\", [\"%s\", \"%s\", \"%s\"],
environ)\n",
        getpid(), nargv[0], nargv[1], nargv[2]);
    execve ("/bin/ls", nargv, environ);

  } else {
    /* the parent just waits 1 second */
    usleep(1000000);
  }

  return 0;
}

---------------------------------------------------------------------------

Now I try to play with it.

> gcc.2.96 -g -Wall -O0 fork.c -o fork

> ldd -v fork
        libc.so.6 => /lib/i686/libc.so.6 (0x40017000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

        Version information:
        ./fork:
                libc.so.6 (GLIBC_2.1.3) => /lib/i686/libc.so.6
                libc.so.6 (GLIBC_2.0) => /lib/i686/libc.so.6
        /lib/i686/libc.so.6:
                ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
                ld-linux.so.2 (GLIBC_2.0) => /lib/ld-linux.so.2
                ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2

> ./fork
[10684] environ[30] =
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/usr/sww/lib:/usr/kerberos/lib:/usr/local/intel/bin/lib:/usr/lib/kde2
[10684] fork()
[10685] execve("/bin/ls", ["ls", "-Flags", "/tmp/k"], environ)
total 24
   4 drwxrwxr-x 2 myself mygroup 4096 Apr 10 14:17 ./
  16 drwxrwxrwt 24 root mygroup 16384 Apr 10 17:50 ../
   4 -rw-rw-r-- 1 myself mygroup 2 Apr 10 14:17
this_is____tmp_k

Here the LD_LIBRARY_PATH points to the main glibc libraries (2.3.2),
so /bin/ls works perfectly.

> env /lib/2.2.4/ld-linux.so.2 --library-path /lib/2.2.4 ./fork
[10700] environ[30] =
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/usr/sww/lib:/usr/kerberos/lib:/usr/local/intel/bin/lib:/usr/lib/kde2
[10700] fork()
[10701] execve("/bin/ls", ["ls", "-Flags", "/tmp/k"], environ)
total 24
   4 drwxrwxr-x 2 myself mygroup 4096 Apr 10 14:17 ./
  16 drwxrwxrwt 24 root mygroup 16384 Apr 10 17:52 ../
   4 -rw-rw-r-- 1 myself mygroup 2 Apr 10 14:17
this_is____tmp_k

Now I'm expliciting that I want the 2.2.4 RTL to be used, and that I
want
the library path to be the one where glibc 2.2.4 resides. It still
works.
I'd say the reason is that the LD_LIBRARY_PATH is still unaffected, so
while the parent process is run with the 2.2.4 libraries, the child is
run with the 2.3.2 ones.

> env LD_LIBRARY_PATH=/lib/2.2.4 /lib/2.2.4/ld-linux.so.2 --library-path /lib/2.2.4 ./fork
[10702] environ[30] = LD_LIBRARY_PATH=/lib/2.2.4
[10702] fork()
[10703] execve("/bin/ls", ["ls", "-Flags", "/tmp/k"], environ)
ls: /lib/ld-linux.so.2: version `GLIBC_2.1.1' not found (required by
/lib/2.2.4/libc.so.6)
ls: /lib/ld-linux.so.2: version `GLIBC_2.2.3' not found (required by
/lib/2.2.4/libc.so.6)
ls: /lib/ld-linux.so.2: version `GLIBC_2.2' not found (required by
/lib/2.2.4/libc.so.6)

Now I'm setting LD_LIBRARY_PATH before expliciting the 2.2.4 RTL. The
parent process works perfectly, and states that its LD_LIBRARY_PATH
points to the 2.2.4 libraries. The child inherits the parent's
environment, so it gets libc.so.6 from the 2.2.4 directory. Alas,
libc.so.6 manages to go back to /lib/ld-linux.so.2, which corresponds
to 2.3.2. We're back to the version hell.

How could I force forked child processes to use the same RTL than
their parent?

Regards.
-pardillaco



Relevant Pages

  • Re: Ruby lacks atfork : The evil that lives in fork...
    ... so that there's no way to ensure mutex to share ... Give the resource to the child. ... fork() in a multi-threaded program. ... multi-threaded I/O libraries, which are almost sure to be invoked ...
    (comp.lang.ruby)
  • Re: Net::SSH::Perl bind socket problem
    ... unfortunatly, I don't quite get how I should use fork. ... the croak code could be the problem, and a possibility could be not to croak so fast, but try port after port until binding has been done or the port range has fully be tested. ... a bit wrong, since you just created a child process, in that childprocess you get the filehandles from the org. ... The parent process can ident his child. ...
    (perl.beginners)
  • Re: fork and exec
    ... process "read" access to the parent process' address space. ... parent and child are identical. ... That's why exec*() exists: if a running program thinks it should be ... Note that the COW scheme is not _necessary_ for fork() to operate. ...
    (comp.unix.programmer)
  • fork and exec
    ... The Linux fork() system call gives both the child process and the ... process "read" access to the parent process' address space. ... why should it call exec system call ????? ...
    (comp.unix.programmer)
  • Re: pthread and async-signal safety.
    ... mix well, unless you use exec*immediately in the child, and even then ... there are problems associated with some systems returning ENOSYS from ... > I stand by my statement that fork() is now mostly useless when ... most libraries should not spawn additional threads. ...
    (comp.unix.programmer)