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

Segfault in unwind #422

Closed
certik opened this issue Sep 15, 2020 · 1 comment
Closed

Segfault in unwind #422

certik opened this issue Sep 15, 2020 · 1 comment

Comments

@certik
Copy link

certik commented Sep 15, 2020

First of all, thank you for this excellent library. I have been using it for a few years and I have been very happy.

I collect stacktraces when exceptions are thrown. When executed inside a test with doctest, the following line will segfault:

  _Unwind_Backtrace(unwind_callback, &d);

Here is the full stack when ran under gdb:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6ad3f4e in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
(gdb) bt
#0  0x00007ffff6ad3f4e in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#1  0x00007ffff6ad511c in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#2  0x00007ffff6ad5ad6 in _Unwind_Find_FDE () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#3  0x00007ffff6ad1b68 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#4  0x00007ffff6ad2d30 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#5  0x00007ffff6ad3a48 in _Unwind_Backtrace () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#6  0x0000555555719140 in LFortran::get_stacktrace_addresses () at /home/ondrej/repos/lfortran/lfortran/src/lfortran/stacktrace.cpp:530

I tried compiling doctest with:

#define DOCTEST_CONFIG_NO_EXCEPTIONS
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#define DOCTEST_CONFIG_IMPLEMENT
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS

But it still happens.

When the _Unwind_Backtrace is called outside of doctest then everything works.

I would think this would happen when the stack is somehow corrupted. Any idea where I should look inside doctest?

@certik
Copy link
Author

certik commented Sep 16, 2020

I got stacktraces working with doctest by defining the main as follows:

#define DOCTEST_CONFIG_NO_EXCEPTIONS
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#define DOCTEST_CONFIG_IMPLEMENT
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#include "doctest.h"

#include <lfortran/config.h>
#include <lfortran/stacktrace.h>

int main(int argc, char** argv)
{
#if defined(HAVE_LFORTRAN_STACKTRACE)
    LFortran::print_stack_on_segfault();
#endif
    return doctest::Context(argc, argv).run();
}

And the test files look like:

#define DOCTEST_CONFIG_NO_EXCEPTIONS
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#include <tests/doctest.h>

#define DOCTEST_CHECK_THROWS_AS(x, y)
#define DOCTEST_CHECK_THROWS_WITH(x, y)

...

Then if the tests throw an exception, it looks like this:

$ ./src/lfortran/tests/test_llvm 
[doctest] doctest version is "2.3.4"
[doctest] run with "--help" for options
LLVM Version:
LLVM (http://llvm.org/):
  LLVM version 9.0.1
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: skylake
terminate called after throwing an instance of 'LFortran::LFortranException'
  what():  xx
Traceback (most recent call last):
  Binary file "/proc/self/exe", in _start()
  File "/build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c", line 310, in __libc_start_main()
  File "/home/ondrej/repos/lfortran/lfortran/src/tests/doctest.cpp", line 17, in main()
    return doctest::Context(argc, argv).run();
  File "/home/ondrej/repos/lfortran/lfortran/src/tests/doctest.h", line 5847, in run()
    tc.m_test();
  File "/home/ondrej/repos/lfortran/lfortran/src/lfortran/tests/test_llvm.cpp", line 27, in _DOCTEST_ANON_FUNC_2()
    throw LFortran::LFortranException("xx");
  File "/home/conda/feedstock_root/build_artifacts/ctng-compilers_1598128761871/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc", line 95, in __cxa_throw()
  File "/home/conda/feedstock_root/build_artifacts/ctng-compilers_1598128761871/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc", line 58, in std::terminate()
  File "/home/conda/feedstock_root/build_artifacts/ctng-compilers_1598128761871/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc", line 48, in __cxxabiv1::__terminate(void (*)())
  File "/home/conda/feedstock_root/build_artifacts/ctng-compilers_1598128761871/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/libsupc++/vterminate.cc", line 95, in __gnu_cxx::__verbose_terminate_handler()
  File "/build/glibc-2ORdQG/glibc-2.27/stdlib/abort.c", line 79, in __GI_abort()
  File "/build/glibc-2ORdQG/glibc-2.27/signal/../sysdeps/unix/sysv/linux/nptl-signals.h", line 80, in __libc_signal_restore_set()
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", in killpg()
Abort: Signal SIGABRT (abort) received

One disadvantage of this approach is that I have to define my own CHECK_THROWS_* macros, since I still want to use those --- I haven't figured out how to make doctest define those, but let all other exceptions through, so that my stacktrace code can show a nice stacktrace for them.

So I think doctest itself works, and I am going to close this issue.

Unfortunately, when the above is used with LLVM that segfaults / throws an exception, the above test program simply hangs. So there is still some problem, but it could be an interaction of LLVM, doctest and my stacktrace framework, and so it needs further debugging to figure out where the problem is.

@certik certik closed this as completed Sep 16, 2020
jhasse pushed a commit to jhasse/doctest that referenced this issue Jan 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant