27

If I run a program from the shell, and it segfaults:

$ buggy_program
Segmentation fault

It will tell me, however, is there a way to get programs to print a backtrace, perhaps by running something like this:

$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)

I'd also rather not use strace or ltrace for that kind of information, as they'll print either way...

6 Answers 6

33

There might be a better way, but this kind of automates it.

Put the following in ~/backtrace:

backtrace
quit

Put this in a script called seg_wrapper.sh in a directory in your path:

#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
    gdb -q $1 core -x ~/backtrace
fi

The ulimit command makes it so the core is dumped. "$@" are the arguments given to the script, so it would be your program and its arguments. $? holds the exit status, 139 seems to be the default exit status for my machine for a segfault.

For gdb, -q means quiet (no intro message), and -x tells gdb to execute commands in the file given to it.

Usage

So to use it you would just:

seg_wrapper.sh ./mycommand and its arguments 

Update

You could also write a signal handler that does this, see this link.

2
  • 3
    Your link to the signal handler solution is dead - this is why answers should not link to other resources...
    – josch
    Sep 26, 2014 at 12:00
  • 1
    you probably mean "-x tells gdb to execute" instead of "-x tells gdb to exit"
    – josch
    Sep 26, 2014 at 12:01
27

Edit:

10 years after I dropped this answer the feature has been deprecated. So if you find that your system/target does not have libSegFault.so seek alternatives.

See commit


Sorry to come in here 2 years later ... stumbled upon while looking for something else. Adding this for completeness.

  1. While I think the accepted answer is great, it requires gdb. The method I am familiar with uses libSegFault.so.

If you run your app with

LD_PRELOAD=...path-to.../libSegFault.so myapp

You would get a report with backtrace, loaded libs, etc

  1. A wrapper script catchsegv is also available that would attempt to use addr2line to translate addresses to filename + line number.

These are much lighter solutions than core files or gdb (good for embedded systems for example)

4
7

catchsegv

It was mentioned in another answer (but in no way focused on). It's a handy tool bundled with the glibc project. It will provide a backtrace (and other useful debug information) only if a program does indeed segfault.

A good write up exists here.

You can include it in your own scripts as you see fit.

1
  • curious - how is this not covered by my answer posted 4 years before yours?
    – nhed
    Jun 11, 2020 at 15:00
6

You need everyone's friend GDB

gdb <program> [core file]

Once you've loaded your corefile, the command 'backtrace' (can be abbreviated to bt) will give you the current call stack. If you run your program from inside gdb, you can set arbitrary breakpoints and examine the memory contents, etc.

1
  • Is there a way to get it just to print the backtrace and exit?
    – Neil
    Sep 2, 2009 at 19:31
4

Ubuntu (as a project) uses Apport to do this. You can look how they did it.

https://wiki.ubuntu.com/Apport

1
  • 2
    +1: Apport mentions some useful mechanisms I wasn't familiar with, like /proc/sys/kernel/core_pattern
    – RobM
    Dec 13, 2011 at 13:38
2

Here is a slightly modified variant of the script from Kyle Brandt. It is improved in the following ways:

  • do not require manual interaction if stack trace is long
  • some coredumps are saved with the name pattern core., respect this setting
  • do not require an explicit command file flying around for gdb (it will create a temporary one)
  • wait for background jobs

Script:

#!/bin/bash
gdbcommandfile=$(tempfile)
usepid=$(cat /proc/sys/kernel/core_uses_pid)
printf "set pagination off\nbacktrace\nquit\n" > $gdbcommandfile
ulimit -c unlimited
"$@"&
pid=$!
wait $!
if [[ $? -eq 139 ]]; then
    if [[ $usepid == 1 ]]; then 
        gdb -q $1 core.$pid -x $gdbcommandfile
    else
        gdb -q $1 core -x $gdbcommandfile
    fi
fi
rm $gdbcommandfile
1
  • 1
    For a chain of such simple commands, I would just use -ex instead. gdb ... -ex 'set pagination off' -ex backtrace -ex quit
    – Josh Stone
    Sep 19, 2016 at 17:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .