Skip to content

Instantly share code, notes, and snippets.

@gchudnov
Last active August 29, 2015 14:07
Show Gist options
  • Save gchudnov/48c6a4b9c974bd6a2a23 to your computer and use it in GitHub Desktop.
Save gchudnov/48c6a4b9c974bd6a2a23 to your computer and use it in GitHub Desktop.
prints stack trace to stderr and file `backtrace-MILLISECONDS.trace`
#ifndef EXT_BACKTRACE_H
#define EXT_BACKTRACE_H 1
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
static void ext_log_backtrace()
{
// TODO: backtrace not implemented
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <execinfo.h>
#include <unistd.h>
#include <sys/time.h>
static int _ext__get_backtrace(char*** strings, int* count)
{
const int backtrace_max_size = 128;
void* buf[backtrace_max_size];
int nptrs = backtrace(buf, backtrace_max_size);
if(!nptrs)
{
fprintf(stderr, "ext_get_backtrace: backtrace failed: '%s'", strerror(errno));
return 0;
}
char** lines = backtrace_symbols(buf, nptrs);
if(!lines)
{
fprintf(stderr, "ext_get_backtrace: backtrace_symbols failed: '%s'", strerror(errno));
return 0;
}
*strings = lines;
*count = nptrs;
return 1;
}
static long _ext__get_milliseconds()
{
timeval t;
if(gettimeofday(&t, NULL) == -1)
{
fprintf(stderr, "ext_get_milliseconds: gettimeofday failed: '%s'", strerror(errno));
return 0;
}
return (t.tv_sec * 1000) + (t.tv_usec / 1000);
}
// filename: backtrace-MILLISECONDS.trace
static char* _ext__make_log_filename()
{
const int max_filename_chars = 64;
char* filename = (char*)malloc(max_filename_chars);
if(filename)
{
snprintf(filename, max_filename_chars, "backtrace-%ld.trace", ext_get_milliseconds());
}
return filename;
}
static void _ext__log_backtrace_file(char** strings, int count)
{
char* filename = _ext__make_log_filename();
if(!filename)
return;
FILE* fp = fopen(filename, "w");
if(!fp)
{
fprintf(stderr, "ext_log_backtrace_file: fopen for '%s' failed: '%s'", filename, strerror(errno));
free(filename);
return;
}
for (int i = 0; i != count; ++i)
{
fprintf(fp, "%s\n", strings[i]);
}
free(filename);
fclose(fp);
}
static void _ext__log_backtrace_stderr(char** strings, int count)
{
for (int i = 0; i != count; ++i)
{
fprintf(stderr, "%s\n", strings[i]);
}
}
// Logs backtrace to stderr and file in the current directory
static void ext_log_backtrace()
{
char** strings;
int count;
if(_ext__get_backtrace(&strings, &count))
{
_ext__log_backtrace_file(strings, count);
_ext__log_backtrace_stderr(strings, count);
free(strings);
}
}
#endif
#endif // #ifndef EXT_BACKTRACE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment