2 years ago

#52469

test-img

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

Accepted video resources