Created
October 17, 2017 15:18
-
-
Save aperezdc/30ad0bcca02301312a290cfee5c476e9 to your computer and use it in GitHub Desktop.
Example on how to dump stack trace on SIGUSR2, useful if program gets stuck
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* unwindtest.c | |
* Copyright (C) 2017 Adrian Perez <aperez@igalia.com> | |
* | |
* Distributed under terms of the MIT license. | |
*/ | |
#define _GNU_SOURCE | |
#include <ucontext.h> | |
#include <dlfcn.h> | |
#include <signal.h> | |
#include <inttypes.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
static void | |
context_backtrace (ucontext_t *context) | |
{ | |
unsigned frame_number = 0; | |
void *ip = NULL; | |
void **bp = NULL; | |
#if defined(REG_RIP) | |
ip = (void*) context->uc_mcontext.gregs[REG_RIP]; | |
bp = (void**) context->uc_mcontext.gregs[REG_RBP]; | |
#elif defined(REG_EIP) | |
ip = (void*) context->uc_mcontext.gregs[REG_EIP]; | |
bp = (void**) context->uc_mcontext.gregs[REG_EBP]; | |
#endif | |
while (bp && ip) { | |
Dl_info dlinfo; | |
if (!dladdr (ip, &dlinfo)) | |
break; | |
const char *symbol = dlinfo.dli_sname; | |
fprintf (stderr, "% 2d: %p <%s+%lu> (%s)\n", | |
++frame_number, | |
ip, | |
symbol ? symbol : "(?)", | |
(uintptr_t) ip - (uintptr_t) dlinfo.dli_saddr, | |
dlinfo.dli_fname); | |
if (dlinfo.dli_sname && strcmp (dlinfo.dli_sname, "main") == 0) | |
break; | |
ip = bp[1]; | |
bp = (void**) bp[0]; | |
} | |
} | |
#define BACKTRACE( ) \ | |
do { \ | |
ucontext_t uc; \ | |
getcontext (&uc); \ | |
context_backtrace (&uc); \ | |
} while (0) | |
static void | |
handle_signal (int signum, siginfo_t *info, void *context) | |
{ | |
context_backtrace ((ucontext_t*) context); | |
} | |
void h (void) { BACKTRACE (); } | |
void g (void) { h (); } | |
void f (void) { g (); } | |
void lh (void) { | |
static volatile int x = 1; | |
while (x) /* noop */; | |
} | |
void lg (void) { lh (); } | |
void lf (void) { lg (); } | |
int main (int argc, char *argv[]) | |
{ | |
f (); | |
struct sigaction sa = { 0, }; | |
sa.sa_sigaction = handle_signal; | |
sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; | |
sigaction (SIGUSR2, &sa, NULL); | |
printf ("PID: %lu\n", (unsigned long) getpid ()); | |
lf (); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment