Hello good people
I'm packaging for CentOS 7 a piece of proprietary software. The software is written in C++14, so I need to use the devtoolset to run it.
Unfortunately I'm having some issues with linking of pthreads. First off I'm getting this warning:
In file included from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr.h:148:0, from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/ext/atomicity.h:35, from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/ios_base.h:39, from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/ios:42, from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/ostream:38, from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/iostream:39, from src/logd-main.cpp:23: /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr-default.h:236:10: warning: 'int __gthrw___pthread_key_create(pthread_key_t*, void (*)(void*)) throw ()' used but never defined __gthrw2(__gthrw_(__pthread_key_create),
…Where the problematic line is a `#include <iostream>`.
Then of course it gets problematic upon linking time
objs/intel-debug/src/logd-main.o:(.rodata+0x8): undefined reference to `__gthrw___pthread_key_create(unsigned int*, void (*)(void*))' collect2: error: ld returned 1 exit status
I searched around on the Web: the classic suggestion (from stackoverflow and such) will be to check for the `-pthread` flag to be present at compilation. This is of course tackled already.
Since the compilation is working in other contexts, I started to wonder if this is some known problem in CentOS + Devtoolset: did someone have similar issues?
Perhaps there's something wrong in how I do the build. Is there in CentOS some software which is using Devtoolset which I could take as example for my build?
Thanks in advance for any suggestion :)
On 2018-05-22, dacav dacav@teknik.io wrote:
Then of course it gets problematic upon linking time
objs/intel-debug/src/logd-main.o:(.rodata+0x8): undefined reference to `__gthrw___pthread_key_create(unsigned int*, void (*)(void*))' collect2: error: ld returned 1 exit status
With a colleague we did some further investigation… and I had some additional understanding.
I could verify that the missing symbol is generated by an header file which belongs to the compiler:
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr-default.h:236:10: warning: 'int __gthrw___pthread_key_create(pthread_key_t*, void (*)(void*)) throw ()' used but never defined BUILDSTDERR: __gthrw2(__gthrw_(__pthread_key_create),
The current CentOS libc, and specifically libpthread.so, does not provide such symbol: it is not reported in `objdump --syms`.
For what I understand, devtoolset is providing static linkage for the functionalities which are not available in the "regular" CentOS libc. That's the role of libstdc++_nonshared.a according to [this stackoverflow post][1]. So I also went for `objdump --syms /opt/rh/devtoolset-6/.../libstd++_nonshared.a`. I found nothing.
So, in short it would seem like I'm not linking against some important object code. This object file might be in the standard CentOS, but more likely in some devtoolset package. The weird part is that `-pthread` should be (in my opinion) take care of all this for me.
At this point I'm somewhat out of bullets :) If someone has some suggestion I will appreciate it. And of course I apologize for the spam.
[1]: https://stackoverflow.com/questions/15599714/risks-of-different-gcc-versions...
Am 22.05.2018 um 15:04 schrieb dacav dacav@teknik.io:
On 2018-05-22, dacav dacav@teknik.io wrote:
Then of course it gets problematic upon linking time
objs/intel-debug/src/logd-main.o:(.rodata+0x8): undefined reference to `__gthrw___pthread_key_create(unsigned int*, void (*)(void*))' collect2: error: ld returned 1 exit status
With a colleague we did some further investigation… and I had some additional understanding.
I could verify that the missing symbol is generated by an header file which belongs to the compiler:
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr-default.h:236:10: warning: 'int __gthrw___pthread_key_create(pthread_key_t*, void (*)(void*)) throw ()' used but never defined BUILDSTDERR: __gthrw2(__gthrw_(__pthread_key_create),
The current CentOS libc, and specifically libpthread.so, does not provide such symbol: it is not reported in `objdump --syms`.
For what I understand, devtoolset is providing static linkage for the functionalities which are not available in the "regular" CentOS libc. That's the role of libstdc++_nonshared.a according to [this stackoverflow post][1]. So I also went for `objdump --syms /opt/rh/devtoolset-6/.../libstd++_nonshared.a`. I found nothing.
So, in short it would seem like I'm not linking against some important object code. This object file might be in the standard CentOS, but more likely in some devtoolset package. The weird part is that `-pthread` should be (in my opinion) take care of all this for me.
At this point I'm somewhat out of bullets :) If someone has some suggestion I will appreciate it. And of course I apologize for the spam.
There exist a backward [1] but not a forward compatibility. IMHO your executable must be build statically. In that sense everything needed is provided by your executable.
[1] https://mirrors.edge.kernel.org/pub/software/libs/glibc/hjl/compat/
-- LF
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr-default.h:236:10: warning: 'int __gthrw___pthread_key_create(pthread_key_t*, void (*)(void*)) throw ()' used but never defined BUILDSTDERR: __gthrw2(__gthrw_(__pthread_key_create),
I forgot to post some follow-up to this story, since I was able to solve it. I'm reporting my findings here, just in case someone else is experimenting the same kind of problem.
Tl;Dr: macros in headers probably contain some bug.
First off, I noticed that this particular symbol is supposed to be a "weak symbol" in the ELF object file, aliasing the internal __pthread_key_create call.
A weak symbol should never trigger a linking problem: in the worst case no regular symbol is supplied, hence the weak definition is used at link time. The linking problem is a clear indication of an error of some kind.
Then I found out that the same definition is included in every single file of the project I was compiling, but only one file was actually obtaining a missing symbol definition.
After a good session of trial-and-error, together with a colleague of mine we figured out that a well placed `#include <thread>` in the beginning of the culprit file was automagically solving everything. By placing that `#include` before anything else, we are probably toggling some `#define` which is preventing the weird situation from happening. Go and figure out what macro gets changed! :)
Interestingly, no thread whatsoever is declared in that file. As a matter of facts, the same software, inclusive of the culprit file, was compiling just fine under different systems.
My suspect is that the whole thing is due to some error in the preprocessor definitions of the involved headers, which screwed up the definition of the weak symbol, and change it into an expected regular symbol.
It must kept in mind that we are talking about compiling C++14 on a somewhat old operating system by means of a backported compiler, so I guess it's a quite peculiar situation.
Cheers, and sorry for the wall-of-text :)