Running a C Program Compiled Here Causes a Glibc Library Not Found Error on Another Server - Is It My Fault or Theirs

Running a C program compiled here causes a GLIBC library not found error on another server - is it my fault or theirs?

You have built on glibc-2.11 system. You are trying to run on a system with glibc-2.3 or older. That's not going to work.

Is it just a matter of me upgrading the C library package

No: upgrading your glibc will only make things worse.

You may want to try solutions listed here.

Is this something we can reasonably request the other party to upgrade their system to support, rather than downgrade our compiler?

Usually the client will strongly resist requests to upgrade their system: it's working fine for them as is, and any upgrade can break other existing applications.

If you are planning to distribute binaries on Linux (as opposed to building them on the target system), then you need to learn how to make binaries that will run everywhere, or you need to state your requirements (minimum kernel and libc versions, etc.) and turn clients who can't meet these requirements away.

Update:

Why did they get two errors. Why didn't they just get one for GLIBC_2.11.1 which is apparently what I built with?

Symbol versioning doesn't work that way.

When a new symbol is introduced, it is marked with the current libc version, e.g. readdir64@@GLIBC_2.2, posix_spawn@@GLIBC_2.15, etc.

When you link a program that uses both of the above symbols, and try to run it on e.g. glibc-2.1 system, you would get two errors.

But if you link a program that doesn't use any of the above symbols, e.g.

int main() { return 0; }

then your program will just run without any errors.

Update 2:

they don't have to add both GLIBC_2.4 and GLIBC2.7 to their Linux system, do they?

No, they don't. The GLIBC_2.11 will have all the previous symbols in it. In fact, they couldn't install both glibc-2.4 and 2.7 even if they wanted to: it is quite difficult to have multiple versions installed at the same time, and impossible to have multiple versions installed in default location.

Applications reporting “libc.so.6: cannot handle TLS data” after upgrading glibc

My understanding is that glibc should be backwards compatible and upgrading it shouldn't cause issues with applications that had previously been working.

That is correct.

Your issue is most likely the result of mismatch between ld-linux and libc.so.6 -- they must come from the same build, of bad things will happen (GLIBC actually consists of many libraries, and they all must match).

It's possible that your 3rd-party provided glibc package is mis-configured and replaced one, but not the other. Possibly it installed libc.so.6 into /usr/local/lib instead of whatever location is appropriate for your OS.

So find all files that "belong" to GLIBC before the installation of 3rd-party update, and verify that every one of them is replaced by it.

It is also possible, though less likely, that the 3rd party package is simply broken, or configured without TLS support.

If you link an app against GLIBC with TLS support, then upgrade GLIBC to one configured without TLS support, the applications will break. That is expected and "normal" (configuring GLIBC without TLS support is simply not a good idea).

Error while importing Tensorflow in Python 2.7 in Ubuntu 12.04. 'GLIBC_2.17 not found'

I had the same problem, so googling I made these steps:

$ sudo pip install --upgrade virtualenv
$ virtualenv --system-site-packages ~/tensorflow
$ cd ~/tensorflow
$ source bin/activate
$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl
$ cd /tmp
$ wget http://launchpadlibrarian.net/137699828/libc6_2.17-0ubuntu5_amd64.deb
$ wget http://launchpadlibrarian.net/137699829/libc6-dev_2.17-0ubuntu5_amd64.deb
$ mkdir libc6_2.17
$ cd libc6_2.17
$ ar p ../libc6_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
$ ar p ../libc6-dev_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
$ cd -
$ LD_LIBRARY_PATH=/tmp/libc6_2.17/lib/x86_64-linux-gnu/ /tmp/libc6_2.17/lib/x86_64-linux-gnu/ld-2.17.so bin/python local/lib/python2.7/site-packages/tensorflow/models/image/mnist/convolutional.py

And to exit:

$ deactivate 

That works for me.

Multiple glibc libraries on a single host

It is very possible to have multiple versions of glibc on the same system (we do that every day).

However, you need to know that glibc consists of many pieces (200+ shared libraries) which all must match. One of the pieces is ld-linux.so.2, and it must match libc.so.6, or you'll see the errors you are seeing.

The absolute path to ld-linux.so.2 is hard-coded into the executable at link time, and can not be easily changed after the link is done (Update: can be done with patchelf; see this answer below).

To build an executable that will work with the new glibc, do this:

g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

The -rpath linker option will make the runtime loader search for libraries in /path/to/newglibc (so you wouldn't have to set LD_LIBRARY_PATH before running it), and the -dynamic-linker option will "bake" path to correct ld-linux.so.2 into the application.

If you can't relink the myapp application (e.g. because it is a third-party binary), not all is lost, but it gets trickier. One solution is to set a proper chroot environment for it. Another possibility is to use rtldi and a binary editor. Update: or you can use patchelf.

How to avoid STT_GNU_IFUNC symbols in your binary?

In general, UNIX systems support backward binary compatibility (a binary built on an old machine continues to run on a newer one), but not the reverse. You can't expect a binary built on a new system to run on an older one. STT_GNU_IFUNC is only the first of many problems you'll encounter.

If you need to build a binary on a newer machine that will run on an older one, see this document.

There used to be "apgcc: A GCC wrapper to make portable binaries" that made this easy (it's referenced from above), but it appears to be gone ;-(

The easiest option is to build on an old machine (I used to build on RedHat 6.2, and the resulting binary ran everywhere). You don't have to actually run RH-6.2 on a physical machine, just bring it up in a VM.

The other relatively easy option is to build in a chroot, again using tools and libraries from an old distribution (e.g. RH-6.2).

What does 'corrupted double-linked list' mean

I have found the answer to my question myself:)

So what I didn't understand was how the glibc could differentiate between a Segfault and a corrupted double-linked list, because according to my understanding, from perspective of glibc they should look like the same thing.
Because if I implement a double-linked list inside my program, how could the glibc possibly know that this is a double-linked list, instead of any other struct? It probably can't, so thats why i was confused.

Now I've looked at malloc/malloc.c inside the glibc's code, and I see the following:

1543 /* Take a chunk off a bin list */
1544 #define unlink(P, BK, FD) { \
1545 FD = P->fd; \
1546 BK = P->bk; \
1547 if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
1548 malloc_printerr (check_action, "corrupted double-linked list", P); \
1549 else { \
1550 FD->bk = BK; \
1551 BK->fd = FD; \

So now this suddenly makes sense. The reason why glibc can know that this is a double-linked list is because the list is part of glibc itself. I've been confused because I thought glibc can somehow detect that some programming is building a double-linked list, which I wouldn't understand how that works. But if this double-linked list that it is talking about, is part of glibc itself, of course it can know it's a double-linked list.

I still don't know what has triggered this error. But at least I understand the difference between corrupted double-linked list and a Segfault, and how the glibc can know this struct is supposed to be a double-linked list:)



Related Topics



Leave a reply



Submit