atexit(3)

โœจ atexit(3) โ€” the "bestie, remind me before we leave" function ๐Ÿ’…

okay so real talk: this is a page from the Library Functions Manual, section 3, and it's all about atexit โ€” registering a function to be called at normal process termination. yes bestie, it's your program's lil goodbye note to itself. ๐ŸŽ€


๐ŸŒธ NAME ๐ŸŒธ

atexit โ€” register a function to be called at normal process termination


๐Ÿงš LIBRARY ๐Ÿงš

Standard C library (libc, -lc)


โœจ SYNOPSIS โœจ

#include <stdlib.h>

int atexit(typeof(void (void)) *function);

๐Ÿ’– DESCRIPTION ๐Ÿ’–

So atexit() takes the function you hand it and registers it to be called when the process ends normally โ€” like, either through exit(3) or by just returning out of your program's main(). Nothing dramatic, no segfaults, just the polite exit. ๐Ÿซถ

Here's the cute part: functions get called in the reverse order of their registration. Last one registered, first one called. It's giving... stack energy. And ngl, no arguments are passed to them, so they better not be expecting a gift. ๐Ÿ˜ญ

You can register the same function multiple times too โ€” it gets called once for every registration. obsessed. It said "and I'll do it again." ๐Ÿ’…

POSIX.1 says an implementation has to allow at least ATEXIT_MAX (32) of these registered at once. The actual limit your implementation supports? You can go find that out with sysconf(3). โœจ

And when a child process gets created via fork(2), it inherits copies of its parent's registrations. But the moment one of the exec(3) functions succeeds? All those registrations are removed. poof. gone. ๐ŸŒˆ


๐Ÿ”ฅ RETURN VALUE ๐Ÿ”ฅ

atexit() returns the value 0 if it worked, and if it didn't, it returns a nonzero value. that's the whole vibe check. ๐Ÿ’€


๐Ÿฆ‹ ATTRIBUTES ๐Ÿฆ‹

For the explanation of the terms used in this section, go peek at attributes(7).

  • Interface: atexit()
  • Attribute: Thread safety
  • Value: MT-Safe

(yes bestie, she's MT-Safe. multithreaded queen. ๐Ÿ‘‘)


โญ VERSIONS โญ

POSIX.1 says the result of calling exit(3) more than once is undefined โ€” and yeah, that includes calling exit(3) from inside a function you registered with atexit(). ๐Ÿ’€

On some systems (but not Linux) this can turn into infinite recursion. So portable programs should not invoke exit(3) inside a function registered using atexit(). periodt. don't do it. ๐Ÿ™ˆ


๐ŸŒˆ STANDARDS ๐ŸŒˆ

C11, POSIX.1-2008.


๐ŸŽ€ HISTORY ๐ŸŽ€

POSIX.1-2001, C89, C99, SVr4, 4.3BSD. she's been iconic since forever, fr fr. ๐Ÿซถ


๐Ÿ’œ NOTES ๐Ÿ’œ

  • Functions registered with atexit() (and with on_exit(3)) are not called if the process dies abnormally because a signal got delivered. rip, no goodbye for you. ๐Ÿ˜ญ
  • If one of your registered functions calls _exit(3), then all the remaining registered functions are not invoked โ€” and the other process termination steps that exit(3) would have done also don't happen. just, like, an abrupt exit. ๐Ÿ’€
  • Here's a fun one: atexit() and on_exit(3) register functions on the same list. So at normal process termination, everything gets invoked in reverse order of registration across both of them. they're sharing a group chat. ๐Ÿซถ
  • Per POSIX.1, the result is undefined if longjmp(3) is used to terminate execution of one of the functions registered using atexit(). so, bestie, don't. ๐Ÿ™ˆ

๐Ÿง Linux notes ๐Ÿง

Since glibc 2.2.3, atexit() (and on_exit(3)) can be used inside a shared library to set up functions that get called when the shared library is unloaded. slay. ๐Ÿ’…


๐ŸŒธ EXAMPLES ๐ŸŒธ

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

static void
bye(void)
{
    printf("That was all, folks\n");
}

int
main(void)
{
    long a;
    int i;

    a = sysconf(_SC_ATEXIT_MAX);
    printf("ATEXIT_MAX = %ld\n", a);

    i = atexit(bye);
    if (i != 0) {
        fprintf(stderr, "cannot set exit function\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

๐Ÿ‘‘ SEE ALSO ๐Ÿ‘‘

dlopen(3), _exit(3), exit(3), on_exit(3)


๐Ÿ’– remember bestie: reverse order, no arguments, and never exit(3) from inside a registered function. iykyk. ๐Ÿ’–

okay that's the whole page ๐ŸŒธ this icon was brought to you by Linux man-pages 6.20, dated 2026-06-05, and it's the atexit(3) page. mwah. ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms