Skip to main content

Printing a backtrace from inside a C program

While digging in the latest code of htop in hunt of a resizing bug I came across calls to functions backtrace(3) and backtrace_symbols_fd(3), which I didn't know about before. htop installs a custom segfault handler which tries to shut down curses and print a stacktrace using the backtrace(3) function. Example output looks like this:

htop 0.9 aborting. Please report bug at http://htop.sf.net
Backtrace: 
htop[0x4081cf]
/lib64/libc.so.6(+0x324c0)[0x7fbbca4a54c0]
/lib64/libc.so.6(__ **sprintf** _chk+0x87)[0x7fbbca558237]
Aborted

While that could be more helpful, it does give ahint that sprintf is involved in the crash - it actually is. Things get interesting when you deal with memory corruption so that the call to backtrace inside your segfault handler segfaults itself. In that case you get:

htop 0.9 aborting. Please report bug at http://htop.sf.net
Segmentation fault

That's not helpful anymore. Still, not all segfaults are memory corruptions!

If you're interested in adding this feature to your own program or at least would like to play with it, here is some dedicated demo code:

/* Licensed as Public Domain */
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>

static void dump_trace() {
    void * buffer[255];
    const int calls = backtrace(buffer,
        sizeof(buffer) / sizeof(void *));
    backtrace_symbols_fd(buffer, calls, 1);
    exit(EXIT_FAILURE);
}

void boom() {
    int a[10];
    printf("%d", a[-100000]);
}

void two() { boom(); }
void one() { two(); }

int main() {
    signal(SIGSEGV, dump_trace);
    one();
    return 0;
}

In my Makefile I have

NUMBERS: backtrace.c
    $(CC) -o $@ $<

NAMES: backtrace.c
    $(CC) **-rdynamic** -o $@ $ <

Without -rdynamic you get numbers, only -- like this:

# ./NUMBERS 
./NUMBERS[0x400683]
/lib64/libc.so.6(+0x324c0)[0x7f129eda04c0]
./NUMBERS[0x4006b1]
./NUMBERS[0x4006db]
./NUMBERS[0x4006eb]
./NUMBERS[0x40070d]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f129ed8cd2d]
./NUMBERS[0x4005c9]

In contrast, with -rdynamic you get function names where available:

# ./NAMES 
./NAMES[0x400953]
/lib64/libc.so.6(+0x324c0)[0x7f59be5d84c0]
./NAMES(boom+0x8)[0x400981]
./NAMES(two+0xe)[0x4009ab]
./NAMES(one+0xe)[0x4009bb]
./NAMES(main+0x20)[0x4009dd]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f59be5c4d2d]
./NAMES[0x400899]

The same job (and a bit more) is also done by library (and tool) stacktrace. I played with it (and put an ebuild into the betagarden overlay) but it's not working for me as expected, yet. I have contacted upstream about it and hope for some enlightening reply in the next few days.

Fwd: The Wackness (2008)

I've just been having good fun with this movie featuring Ben Kingsley:

On a side note it seems to me that faces work like grammars and languages (speaking of theoretical computer science). Again and again a face reminds me of another, Olivia Thirlby of Rachel McAdams this time. I cannot name the building blocks their faces share but it does look like use of the same grammar to me. Anyway...

svneverever 1.2.0 released

In some cases previous versions of svneverever would report too high numbers for the revision a directory was last seen on. Let me quote from Wouter Haffmans' excellent bug description (accompanied by a patch):

$ svnadmin create test
$ cd test
$ svn mkdir "file://`pwd`/parent" -m "Add parent (r1)"
$ svn mkdir "file://`pwd`/parent/child" -m "Add child (r2)"
$ svn rm "file://`pwd`/parent/child" -m "Del child (r3)"
$ svn rm "file://`pwd`/parent" -m "Del parent (r4)"

svneverever prints, for this repository:
(1; 3)  /parent
(2; 3)      /child

Expected:
(1; 3)  /parent
(2; 2)      /child

So that is fixed in 1.2.0.

Fresh: Freeverb3 2.5.16

Just a quick note: Freeverb3, a reverb plug-in for Audacious (and a few other interfaces), just grew to version 2.5.16 in Gentoo. It's the first release of Freeverb3 compiling against Audacious 2.5.x: Audacious upstream has broken API-compatibility on more time. Previous users of Freeverb3 2.5.14.1 will also notice the arrival of a new effect called "Gardner Largeroom". Enjoy.

Lossless JPEG rotation preserving EXIF data

It's known that there are ways to losslessly rotate a JPEG image. One tool supporting lossless rotation is jpegtran, a free software command line app coming with the JPEG libraries. By default, jpegtran copies JPEG comments only: EXIF data is not copied. No warning is printed. Sadly I learned that only recently. To rotate image I am now using this command:

# jpegtran -rotate 90 -copy all -perfect \
    -optimize -progressive INPUT.jpg > OUTPUT.jpg

The -copy all is turn on copying of EXIF data.

Howto late-join a mail thread seamlessly technically

Say you joined a mailing list just to jump onto a specific mail thread that someone brought to your attention. To have your mail join the thread seamlessly (in a way many mail clients support) you need

  1. the mail's subject
  2. the message id of the parent to attach to
  3. a mail client allowing to add headers In-Reply-To and References.

The message ID header is easy to find once you have mail headers at hand:

Message-ID: <foo123@example.org>

If you#re lucky you get them from a mail archive or a friend who's subscribed already. Now a child of that mail would carry these headers:

In-Reply-To: <foo123@example.org>
References: <foo123@example.org>

If you're using Thunderbird, you can make it show headers In-Reply-To and References for selection in the mail composition window. All you need to do is open the advanced config GUI editor (sometimes called about:config, Menu > Edit > Preferences > Advanced > Config Editor ...), select field mail.compose.other.header and set it to In-Reply-To,References. I learned about that field myself from here. If you have updates on this procedure, please comment below. Thanks!