2

I have a C program that quits unexpectedly on Linux and I have a hard time finding out why (no core dump, see XIO: fatal IO error 11). I placed an atexit() at the beginning of the program and the callback function is indeed being called when the crash happens.

How can I know what called the atexit callback function? From reading the man page, atexit is called at exit (d'ho!) or return from main. I can exclude the latter because there are a bunch of printf at the end of the main and I don't see them. And I can exclude the former simply because there aren't any exit() in my program.

That leaves only one solution: exit is being called from a library function. Is that the only possibility? And how can I know from where? Is it possible to print out a stack trace or force a core dump from inside the atexit callback?

Jens
  • 69,818
  • 15
  • 125
  • 179
dargaud
  • 2,431
  • 2
  • 26
  • 39
  • 2
    Which platform are you targeting ? Windows, Linux, other ? We may find specific API functions that will help you. – blue112 Oct 08 '14 at 12:34
  • 2
    "I have a C program that quits unexpectedly on Linux" i guess he's targeting linux? – MrSykkox Oct 08 '14 at 12:48
  • Put something *really* bad in your current `atexit` function. Divide-by-zero? Stack over/underflow? Memory allocation failure? (Unfortunately I only get these kind of errors by accident, never on purpose, so I cannot recommend any method in particular.) – Jongware Oct 08 '14 at 12:55
  • Regarding your forcing a core dump question, there is ***[good discussion here](http://stackoverflow.com/q/17965/645128)*** about how to do that. – ryyker Oct 08 '14 at 13:10
  • If your program is unexpectedly quitting, it may not call exit() at all. You can use `ltrace -S` to watch the program's execution until it quits, then use a debugger to plant a breakpoint at a point that is just before it quits, and examine things in more detail. – Mark Plotnick Oct 09 '14 at 14:21
  • I tried ltrace but the exit seems to be called from a library function, which ltrace skips over. Haven't tried -S though. The problem may be the log size (prog runs for several days before it crashes). – dargaud Oct 09 '14 at 14:27

2 Answers2

7

Call e.g. abort() in your atexit handler, and inspect the coredump in gdb. The gdb backtrace command shows you where it exits, if the atexit handler is run. Here's a demonstration:

#include <stdlib.h>


void exit_handler(void)
{
    abort();
}

void startup()
{
#ifdef DO_EXIT
    exit(99);
#endif
}


int main(int argc, char *argv[])
{
    atexit(exit_handler);

    startup();

    return 0;
}

And doing this:

$ gcc -DDO_EXIT -g atexit.c
$ ulimit -c unlimited
$ ./a.out
Aborted (core dumped)
$ gdb ./a.out core.28162
GNU gdb (GDB) Fedora 7.7.1-19.fc20
..
Core was generated by `./a.out'.
Program terminated with signal SIGABRT, Aborted.
#0  0xb77d7424 in __kernel_vsyscall ()
Missing separate debuginfos, use: debuginfo-install glibc-2.18-16.fc20.i686
(gdb) bt
#0  0xb77d7424 in __kernel_vsyscall ()
#1  0x42e1a8e7 in raise () from /lib/libc.so.6
#2  0x42e1c123 in abort () from /lib/libc.so.6
#3  0x0804851b in exit_handler () at atexit.c:6
#4  0x42e1dd61 in __run_exit_handlers () from /lib/libc.so.6
#5  0x42e1ddbd in exit () from /lib/libc.so.6
#6  0x0804852d in startup () at atexit.c:12
#7  0x08048547 in main (argc=1, argv=0xbfc39fb4) at atexit.c:21

As expected, it shows startup() calling exit.

You can ofcourse debug this interactively too, start your program in gdb and set a breakpoint in the atexit handler.

nos
  • 223,662
  • 58
  • 417
  • 506
4

The standard only says "at normal program termination", so maybe on Linux this is more than exit or return from main. Also you forgot pthread_exit, which also may terminate the thread of main and thus the whole program.

In any case, there is no way to see immediatly from where the termination was issued. The atexit handlers are usually called by the initializtion function. By definition all other application code, but the atexit handlers are gone at that point.

You could try to trace execution through a debugger no nail the place where the termination happens down.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177