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

Static library can't use exceptions internally with GNU C++ toolchain #3893

Open
yilinwei opened this issue Apr 25, 2024 · 5 comments
Open
Labels

Comments

@yilinwei
Copy link
Contributor

Hi,

I might not be using the correct linker flags, but I can't see to get a Scala native lib to be linked with any combination of flags which allows exceptions to be used in the underlying library.

This is on x86_64 Linux. I see the same issue on the github runners as well on ubuntu-22.04 .

Here is the repro https://github.com/yilinwei/scala-native-issue. I have tried clang versions from 14 through to 17 with no luck.

@yilinwei
Copy link
Contributor Author

yilinwei commented Apr 26, 2024

So, weirdly, this works if you pass -O1 as a compile flag when creating the static archive. I'm deeply concerned that an optimizer flag changes semantics of the code though.

EDIT: Consuming the archive in a rust project still has the same uncaught exception.

EDIT: -O1 seems to optimize some of the exceptions to JMP instructions I think it evicts the libunwind symbols in the binary and hence we call the _UnwindXX functions directly on the platform.

@WojciechMazur
Copy link
Contributor

Thank you for the reproducer, we'll try to investigate it soon. The theory about direct calls could make sens, I wonder if we can somehow prevent it. Maybe we can somehow hint LLVM to change this behaviour

@yilinwei
Copy link
Contributor Author

yilinwei commented Apr 27, 2024

This is the backtrace I got from running a variant of the problematic code (running on 0.5.x and clang 17 to mirror the vendored libunwind) which fails with the same error.

Notice on frame 9, _Unwind_Resume_or_Rethrow, is from libgcc_s rather than the vendored library.

* thread #1, name = 'a.out', stop reason = signal SIGABRT
    frame #0: 0x00007ffff7aa3ddc libc.so.6`__pthread_kill_implementation + 268
    frame #1: 0x00007ffff7a549c6 libc.so.6`raise + 22
    frame #2: 0x00007ffff7a3d8fa libc.so.6`abort + 215
    frame #3: 0x00007ffff7cb6fea libstdc++.so.6`__gnu_cxx::__verbose_terminate_handler() + 282
    frame #4: 0x00007ffff7cb4f8a libstdc++.so.6`__cxxabiv1::__terminate(void (*)()) + 10
    frame #5: 0x00007ffff7cb3ff9 libstdc++.so.6`__cxa_call_terminate + 57
    frame #6: 0x00007ffff7cb4716 libstdc++.so.6`__gxx_personality_v0 + 134
    frame #7: 0x0000555555661902 a.out`unwind_phase2 + 290
    frame #8: 0x000055555566161e a.out`_Unwind_RaiseException + 142
    frame #9: 0x00007ffff7ed9399 libgcc_s.so.1`_Unwind_Resume_or_Rethrow + 41
    frame #10: 0x00007ffff7cb528b libstdc++.so.6`__cxa_rethrow + 59
    frame #11: 0x00007ffff7ca9a96 libstdc++.so.6`__gnu_cxx::__verbose_terminate_handler() (.cold) + 109
    frame #12: 0x00007ffff7cb4f8a libstdc++.so.6`__cxxabiv1::__terminate(void (*)()) + 10
    frame #13: 0x00007ffff7cb3ff9 libstdc++.so.6`__cxa_call_terminate + 57
    frame #14: 0x00007ffff7cb4716 libstdc++.so.6`__gxx_personality_v0 + 134
    frame #15: 0x0000555555661902 a.out`unwind_phase2 + 290
    frame #16: 0x000055555566161e a.out`_Unwind_RaiseException + 142
  * frame #17: 0x00007ffff7cb523a libstdc++.so.6`__cxa_throw + 58
    frame #18: 0x0000555555669eb5 a.out`scalanative_throw + 69
    frame #19: 0x0000555555620b0f a.out`_SM4Foo$D15$anonfun$smth$1nEPT4Foo$ + 63
    frame #20: 0x0000555555620bcc a.out`_SM14Foo$$$Lambda$1D5applyL16java.lang.ObjectEO + 28
    frame #21: 0x00005555556aab8a a.out`_SM15scala.Function0D12apply$mcV$spuEO + 42
    frame #22: 0x0000555555620829 a.out`_SM4Foo$D10someMethoduEO + 121
    frame #23: 0x0000555555620c89 a.out`_SM4Lib$D3bariuEO + 105
    frame #24: 0x0000555555620bff a.out`lib_bar + 15
    frame #25: 0x0000555555620783 a.out`main + 19
    frame #26: 0x00007ffff7a3efce libc.so.6`__libc_start_call_main + 126
    frame #27: 0x00007ffff7a3f089 libc.so.6`__libc_start_main@@GLIBC_2.34 + 137
    frame #28: 0x00005555556206a5 a.out`_start + 37 

@yilinwei yilinwei changed the title Static library can't use exceptions internally Static library can't use exceptions internally with GNU C++ toolchain Apr 27, 2024
@yilinwei
Copy link
Contributor Author

yilinwei commented Apr 29, 2024

@WojciechMazur

I was thinking a little more and I'm convinced that we shouldn't bundle libunwind when creating a library (static or dynamic). If users are pulling a scala native lib into other runtimes and multiple symbols are present for unwinding, the behaviour gets extremely strange.

For example, I see issues like #3296 appearing on MacOS as well, even though we don't get the termination error while building the static library and linking against it.

Can you think of a reason why we shouldn't strip the objects out in the sbt plugin when building a library?

@yilinwei
Copy link
Contributor Author

yilinwei commented May 4, 2024

Hi,

I did a bit more of an investigation since I'm trying to use Scala Native as a library.

There are a few problems which I've found:

  1. libunwind isn't really available on all distros easily. For example RHEL 8 removed it.
  2. Most other toolchains, don't really expect libunwind to be bundled by libraries; building a scala native library with a Rust project or C++ project will cause very weird behaviour
  3. Evicting the symbols, isn't enough. libgcc_s does not expose the functions that we use.

Having said that I do not see why we could not use the functions mentioned here, plus the gcc extension method _Unwind_Backtrace which seems to be well supported. It looks as though Rust's backtrace library is doing the same thing.

I have put together a (simplified) example of the proposed changes on this branch to show it working where I:

  1. Remove the problematic objects.
  2. Use the other API by shadowing the current functions.

wdyt?

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

No branches or pull requests

2 participants