Code Monkey home page Code Monkey logo

deathhandler's Introduction

DeathHandler C++03+ class installs SEGFAULT, SIGABRT and SIGFPE signal handlers to print a nice stack trace and (if requested) generate a core dump. In DeathHandler's constructor, signal handlers are installed through sigaction(). If your program encounters a segmentation fault, the call stack is unwinded with backtrace(), converted into function names with line numbers via addr2line (fork() + execlp()). Addresses from shared libraries are also converted thanks to dladdr(). All C++ symbols are demangled. Printed stack trace includes the faulty thread id obtained with pthread_self() and each line contains the process id to distinguish several stack traces printed by different processes at the same time.

The code works primarily on Linux and tested on x86_64 and ARM with glibc. Besides, there is a partial support of MacOSX (addr2line -> atos is not implemented).

Since backtrace() uses malloc() and the heap my be corrupted by the time it is called, malloc() and free() have to be overridden. On Linux, it is done via a simple symbol overload; on MacOSX, malloc_default_zone() approach is taken because overloading does not work out of the box.

Example

test.cc:

#include "death_handler.h"

int main() {
  Debug::DeathHandler dh;
  int* p = NULL;
  *p = 0;
  return 0;
}
g++ -g death_handler.cc test.cc -ldl -o test
./test

This project is released under the Simplified BSD License. Copyright 2012 Samsung R&D Institute Russia, 2016 Moscow Institute of Physics and Technology.

deathhandler's People

Contributors

j1elo avatar mariuszmaximus avatar oli-arborum avatar vmarkovtsev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deathhandler's Issues

death_handler.cc:(.text+0xf14): undefined reference to `dladdr'

hello,
I must use it wrong but everything I do a get this error.

 #include "death_handler.h"
 int main() {
   Debug::DeathHandler dh;
  int* p = NULL;
  *p = 0;
  return 0;
   }
g++ test.cc
Target: i686-linux-gnu
Configuré avec: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Modèle de thread: posix
gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)

I think this tool can be great and I hope you can help me =)

Free in death_handler.cpp:93 enless loop?

My program is rather complex, so I'm not sure this is caused by deathhandler exclusively. I'm also using asan. Any ideas why this might happen?

What's good info to provide?

$ gdb -ex run myapp
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff396a4d4 in dlsym () from /usr/lib/libdl.so.2
(gdb) bt
#0  0x00007ffff396a4d4 in dlsym () from /usr/lib/libdl.so.2
#1  0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#2  0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#3  0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#4  0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#5  0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#6  0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#7  0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#8  0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#9  0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#10 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#11 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#12 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#13 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#14 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#15 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#16 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#17 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#18 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#19 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#20 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#21 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#22 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#23 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#24 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#25 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#26 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#27 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#28 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#29 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#30 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#31 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#32 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#33 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#34 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#35 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#36 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#37 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#38 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#39 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#40 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#41 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
#42 0x00007ffff396a520 in dlsym () from /usr/lib/libdl.so.2
#43 0x0000555555dea1c6 in free (ptr=0x7ffff76fb840 <alloc_memory_for_dlsym+32>) at /home/hrehfeld/projects/mplan-repos3-git/mplan/ext/DeathHandler/death_handler.cc:93
#44 0x00007ffff396abad in ?? () from /usr/lib/libdl.so.2
...

Remove dependency with gtest

Hi, I don't have control over packages in my environment or admin privileges. First time compiling reveals that gtest.h is not found. Any chance I can get around this issue?

good job!

  1. DeathHandler is a nice job! I'm going to use it in my simple C++ Logging tool. Thanks very much!
  2. It seems <pthread.h> and <cxxabi.h> are not used in DeathHandler.cc

pragma for GCC 5+

Lines 328 and 598 of death_handler.cc should be changed to read:

#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)

to handle GCC 5 and above.

Staticly linking with tcmalloc incurs multiple definition of `malloc/free`

I use DeathHandler in my c++ project with tcmalloc. Building static binaries encounters this

gperftools-2.5/lib/libtcmalloc.a(libtcmalloc_la-tcmalloc.o): multiple definition of 'malloc'
(death_handler.cc.o): previous definition here
gperftools-2.5/lib/libtcmalloc.a(libtcmalloc_la-tcmalloc.o): multiple definition of 'free'
(death_handler.cc.o): previous definition here

What can I do?

sigaltstack?

This is great work.
I see you use SA_ONSTACK so I assume you intended to provide an alternate stack (which is better for this case) but I don't see anywhere an initialization with sigaltstack - or maybe I missed something?
Per sigaction man page, in such case the default stack is used (which I assume is as if SA_ONSTACK has not been given)

Feature requests: Output format suitable for logs: constructor setting for logfile output

I have used DeathHandler for catching and describing segfaults during runs of unit tests on Jenkins, where it was not practical to catch core files or run gdb.

However the text has embedded cursor control sequences.

It would be useful to also provide a constructor
DeathHandler::DeathHandler(boolean forLogs)

which if given 'true' disabled ALL cursor escape sequences in the output and delivered pure text.

How to increase backtraces?

Hi,

Thanks for the efforts. May I know how to increase number of back traces? The following output doesn't provide sufficient information to troubleshoot. Thanks.

^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 ^[[31;1mSegmentation fault^[[0m (thread ^[[33;1m3020847040^[[0m, pid ^[[33;1m29224^[[0m) 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 
Stack trace:
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 ^[[34;1m[QCoreApplication::notifyInternal2(QObject*, QEvent*)]^[[0m
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 /usr/local/qt5pi/lib/libQt5Core.so.5^[[32;1m:0x284470^[[0m
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 ^[[34;1m[QTimerInfoList::activateTimers()]^[[0m
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 /usr/local/qt5pi/lib/libQt5Core.so.5^[[32;1m:0x2e1e6c^[[0m
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 ^[[34;1m[QEventDispatcherGlib::flush()]^[[0m
 
^[[0;31mFATAL^[[0m 2022-05-23T18:51:39 /usr/local/qt5pi/lib/libQt5Core.so.5^[[32;1m:0x2e26a0^[[0m

Information: addr2line returns ?? with newer GCC compiler (-no-pie)

This function always worked for me until i upgraded my GCC compiler.
The addr2line function wasn't able to get the filename and line numbers anymore.
It returned ??:0 for every address.

I figured that the reason it doesn't work is because the newer GCC is using -pie by default. Thus, using -no-pie fixes it.

Segmentation fault in Debug::addr2line

strstr(line, "\n") returns NULL if a newline is not found. Dereferencing without a NULL check causes a segmentation fault.

if (*(strstr(line, "\n") + 1) == '?') {

strcpy(strstr(line, "\n") + 1, image); // NOLINT(runtime/printf)

A bug in addr2line causes it to produce outputs such as the following for actually valid binaries:

addr2line: DWARF error: section .debug_info is larger than its filesize! (0x93ef57 vs 0x530ea0)\n

And for whatever reason, line will occasionally be read only partially through the pipe, e.g.:

addr2line: DWARF error: section .debug_info is larger than its filesize! (0x93ef57 vs 0x

I do not know whether the partial read is specifically related to this error or if it also happens with valid addr2line output. Either way, the partial read causes line not to have a trailing newline. Therefore, strstr returns NULL and the dereference of NULL + 1 causes a segmentation fault.

SIGFPE?

This is such a great tool! If I want to add SIGFPE as being handled, do you think I need to do anything special other than follow the existing code as a template?

compile for embeeded don't show stack

It looks like DeathHandler is exactly what I need for my problem on a small ARM controller running Debian.
The development environment is on my Intel desktop PC with an chroot environment for armel to compile and link executable - usually works fine.
But I don't see anything below "Stack trace" line in case I rsync the new binary over to my ARM controller. I've testet the sources:
#include "death_handler.h" int main() {   Debug::DeathHandler dh;  int* p = NULL;   *p = 0;   return 0; }
made on chroot environment with
g++ -O2 -g death_handler.cc test.cc -ldl -o test
started with
./test
showing OK on chroot:
Segmentation fault (thread 0, pid 4198) Stack trace: [main] test.cc:5 0x15694 at /lib/arm-linux-gnueabi/libc.so.6 qemu: uncaught target signal 6 (Aborted) - core dumped [1]+  Aborted                 (core dumped) ./test
but showing NOK after rsync and exec on ARM:
Stack trace: [1]+ Aborted ./test

I've already tried to also rsync the source file test.cc over, but still no success.
What do I need to do to see the stack trace with source-filenames and line-numbers on another machine?

Thanks
Achim

LD_PRELOAD

Is it possible to adapt DeathHandler so that it can be used in a similar style to that of libSegFault.so.

$ LD_PRELOAD=/lib/libSegFault.so ./foo

Or is there some requirement that makes it necessary to directly compile programs against DeathHandler?

Thanks

Question: What to do to write stack trace to file instead of stderr?

I tried to change the code to write to a file instead of stderr, but I failed.
I added a member variable output_fileno_ and a method to set the filename of the output. Default is output to stderr:

int DeathHandler::output_fileno_ = STDERR_FILENO;

bool DeathHandler::set_output_filename(const char* filename) {
  if (output_fileno_ != STDERR_FILENO) {
    close( output_fileno_ );
  }
  int fp = open(filename, O_APPEND);
  if (fp != -1) {
    output_fileno_ = fp;
  }
  return (fp != -1);
}

Then I changed this function

INLINE void print2stderr(int fileno, const char *msg, size_t len = 0) {
  if (len > 0) {
    checked(write(fileno, msg, len));
  } else {
    checked(write(fileno, msg, strlen(msg)));
  }
}

and added the output_fileno_ parameter to each call.

I close output_fileno_ in DTOR if output_fileno_ != STDERR_FILENO, but it does not seem to work (program hangs somewhere...). No idea.
Unfortunately I am not very familiar with C file IO (using C++ iostreams normally).
Do You have any hints?

Support for aarch64

Hello
How are you?
Thanks for contributing this project.
I am going to use your handler on ARM 64 bit Linux(aarch64).
Could u support aarch64 asap?
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.