2 years ago
#52469
brodo
std::rethrow_exception compatibility with libc++ and libstdc++?
I have a shared library compiled with --stdlib=libc++
which makes use of std::rethrow_exception()
.
I need to load and use this library from an executable (node
) that loads libstdc++
.
I have found that any exception thrown by my library using std::rethrow_exception()
did not get caught and crashed the application.
By further investigation I found that I could catch the exception using a catch(...)
block, but I could not get any information about the exception.
I think the issue might be some sort of ABI compatibility issue between libc++ and libstdc++`.
Here is a small code snippet that reproduces the issue:
// libtest.h
void use_rethrow();
// libtest.cc
// compiled using clang++-12 --stdlib=libc++ -shared -fPIC libtest.cc -o libtest.so
#include <stdexcept>
void use_rethrow()
{
try
{
throw std::runtime_error("runtime error");
}
catch (std::exception& ex)
{
auto eptr = std::current_exception();
std::rethrow_exception(eptr);
}
}
// main.cc
#include <iostream>
#include "libtest.h"
int main()
{
try
{
use_rethrow();
}
catch(std::exception& ex)
{
std::cout << "OK: Caught exception: " << ex.what() << std::endl;
}
catch(...)
{
std::cout << "FAIL: Caught something" << std::endl;
}
return 0;
}
Output:
$ clang++-12 -L. -ltest main.cc
$ ldd a.out
linux-vdso.so.1 (0x00007fff25894000)
libtest.so => not found
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2b73486000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2b73337000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f2b7331c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2b7312a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2b73691000)
$ LD_LIBRARY_PATH=. ./a.out
FAIL: Caught something
But if I compile the test application using --stdlib=libc++
, this works as I'd expect:
$ clang++-12 -L. -ltest --stdlib=libc++ main.cc
$ ldd a.out
linux-vdso.so.1 (0x00007ffcf1fc2000)
libtest.so => not found
libc++.so.1 => /lib/x86_64-linux-gnu/libc++.so.1 (0x00007f84e64c2000)
libc++abi.so.1 => /lib/x86_64-linux-gnu/libc++abi.so.1 (0x00007f84e648a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f84e633b000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f84e6320000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f84e612e000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f84e6109000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f84e60fe000)
libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f84e60f4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f84e65ba000)
$ LD_LIBRARY_PATH=. ./a.out
OK: Caught exception: runtime error
$
$ #but I can get the same unexpected behavior by preloading libstdc++
$ LD_PRELOAD=/lib/x86_64-linux-gnu/libstdc++.so.6 LD_LIBRARY_PATH=. ./a.out
FAIL: Caught something
This issue affects std::promise
and std::future
as well, since they use std::rethrow_exception()
.
The question is: how do I catch exceptions thrown using std::rethrow_exception()
when both libstdc++ and libc++ are runtime loaded?
c++
linux
exception
libstdc++
libc++
0 Answers
Your Answer