Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libstdc++ must use thread-local errno #45

Open
jclulow opened this issue May 28, 2021 · 2 comments
Open

libstdc++ must use thread-local errno #45

jclulow opened this issue May 28, 2021 · 2 comments

Comments

@jclulow
Copy link
Member

jclulow commented May 28, 2021

It would seem that libstdc++.so.0.6.28 does not end up built with -D_TS_ERRNO defined (e.g., via -D_REENTRANT). This results in errno checks in, for example, std::filesystem::status() looking at the global errno rather than using *___errno() as it should to local the thread-specific error number.

This was noticed when trying to use Clickhouse, a large C++ program that makes heavy use of threads. The std::filesystem::exists() call would throw unexpectedly for files or directories that did not exist -- but it would report "Error 0" as the reason.

It's possible to pass -D_TS_ERRNO in via CFLAGS and CXXFLAGS while building GCC -- but I expect we should enable this by default and always in the source itself, in order to ensure correct binaries are always created.

@jclulow
Copy link
Member Author

jclulow commented May 28, 2021

Looking a bit closer to demonstrate the use of the errno global, first in the source:

stat_type st;
if (posix::stat(str, &st))
{
int err = errno;
ec.assign(err, std::generic_category());

And then in the disassembly on an OmniOS r151038c machine:

 $ mdb -e '$G; _ZNSt10filesystem6statusERKNS_7__cxx114pathERSt10error_code+0x26::dis -n 3' \
    /usr/gcc/10/lib/amd64/libstdc++.so.6.0.28
C++ symbol demangling enabled
std::filesystem::status+0x1d:   call   -0xd1a7a <PLT:stat>
std::filesystem::status+0x22:   testl  %eax,%eax
std::filesystem::status+0x24:   je     +0x5a    <std::filesystem::status+0x80>
std::filesystem::status+0x26:   movq   +0x5796b(%rip),%rax      <0x22c658>
std::filesystem::status+0x2d:   movl   $0xffff,%r13d
std::filesystem::status+0x33:   movl   (%rax),%ebx
std::filesystem::status+0x35:   call   -0xd5112 <PLT:_ZNSt3_V216generic_categoryEv>

Note that after the call to stat() we move a value through a relocated pointer (0x22c658):

$ elfdump /usr/gcc/10/lib/amd64/libstdc++.so.6.0.28 | grep 0x22c658
  R_AMD64_GLOB_DATA                  0x22c658                  0  .SUNW_reloc    errno

On a machine where we passed -D_TS_ERRNO during the build of GCC 10, we instead see a call to ___errno() as expected:

$ mdb -e '$G; _ZNSt10filesystem6statusERKNS_7__cxx114pathERSt10error_code+0x26::dis -n 3' \
    /usr/gcc/10/lib/amd64/libstdc++.so.6.0.28
C++ symbol demangling enabled
std::filesystem::status+0x1d:   call   -0xd19aa <PLT:stat>
std::filesystem::status+0x22:   testl  %eax,%eax
std::filesystem::status+0x24:   je     +0x5a    <std::filesystem::status+0x80>
std::filesystem::status+0x26:   call   -0xd3cf3 <PLT:___errno>
std::filesystem::status+0x2b:   movl   $0xffff,%r12d
std::filesystem::status+0x31:   movl   (%rax),%ebx
std::filesystem::status+0x33:   call   -0xd5040 <PLT:_ZNSt3_V216generic_categoryEv>

@jclulow
Copy link
Member Author

jclulow commented May 28, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant