0

Out of curiosity I am trying to get the libc on_exit function to work, but I have run into a problem with a segmentation fault. The difficulty I am having is finding an explanation of the proper use of this function. The function is defined in glibc as:

Function: int on_exit (void (*function)(int status, void *arg), void *arg) This function is a somewhat more powerful variant of atexit. It accepts two arguments, a function and an arbitrary pointer arg. At normal program termination, the function is called with two arguments: the status value passed to exit, and the arg.

I created a small test, and I cannot find where the segmentation fault is generated:

#include <stdio.h>
#include <stdlib.h>

void *
exitfn (int stat, void *arg) {
  printf ("exitfn has been run with status %d and *arg %s\n", stat, (char *)arg);
  return NULL;
}

int
main (void)
{
  static char *somearg="exit_argument";
  int exit_status = 1;

  on_exit (exitfn (exit_status, somearg), somearg);
  exit (EXIT_SUCCESS);
}

Compiled with: gcc -Wall -o fn_on_exit fnc-on_exit.c

The result is:

$ ./fn_on_exit
exitfn has been run with status 1 and *arg exit_argument
Segmentation fault

Admittedly, this is probably readily apparent for seasoned coders, but I am not seeing it. What is the proper setup for use of the on_exit function and why in this case is a segmentation fault generated?

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Portability node: `atexit` is Standard C; `on_exit` is *ad hoc* and not part of any standard, as far as I can see. – M.M Mar 15 '14 at 08:39
  • Correct, GNU libc specifies on_exit is included in the GNU C library only for compatibility for SunOS, and may not be supported by other implementations. However, being there, it does provide a mechanism for conditional termination/cleanup based on 'int status' or 'void *arg' if that is something needed in a particular piece of code. Presumably that is the reason for it's mention as a more robust alternative to atexit. – David C. Rankin Mar 16 '14 at 23:04

1 Answers1

4

The line of code

  on_exit (exitfn (exit_status, somearg), somearg);

Should be

  on_exit (exitfn, somearg);

As you do not want to call the exitfn at this stage (that returns NULL!)

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • Thank you. I knew it was a forest-for-the-trees issue. The modifications required were: to make it 'void exitfn' instead of 'void * exitfn' and then use on_exit as you specified 'on_exit (exitfn, somearg)' – David C. Rankin Mar 16 '14 at 22:21
  • Additionally, changing exitfn from 'void *' to 'void' requires removal of 'return NULL'; as well. – David C. Rankin Mar 16 '14 at 22:56
  • @DavidC.Rankin I did not wish to rub salt into the wounds – Ed Heal Mar 17 '14 at 07:32
  • no salt, I really appreciate the help. I had read the glibc definition of on_exit use -- literally, and was stumped. Seeing the solution made immediate sense, but left to my own devices, it would have taken a really long time to get there. Thank you! – David C. Rankin Mar 18 '14 at 06:55
  • @EdHeal how to pass several arguments to `on_exit`? – user2284570 Dec 20 '20 at 23:06
  • Put them in a `struct` and use a pointer to this `struct` as `somearg` – Ed Heal Dec 24 '20 at 23:23