diff --git a/stdlib/tst-atexit-common.c b/stdlib/tst-atexit-common.c index 262235a478..99b00bf3aa 100644 --- a/stdlib/tst-atexit-common.c +++ b/stdlib/tst-atexit-common.c @@ -21,11 +21,20 @@ #include #include #include +#include #define MAX_ATEXIT 20 /* Large enough for current set of invocations. */ static char crumbs[MAX_ATEXIT]; static int next_slot = 0; +/* Helper: flush stdout and _exit. */ +static void +_exit_with_flush (int code) +{ + fflush (stdout); + _exit (code); +} + static void fn0 (void) { @@ -60,11 +69,11 @@ fn_final (void) const char expected[] = "3021121130211"; if (strcmp (crumbs, expected) == 0) - _exit (0); + _exit_with_flush (0); printf ("crumbs: %s\n", crumbs); printf ("expected: %s\n", expected); - _exit (1); + _exit_with_flush (1); } /* This is currently just a basic test to verify that exit handlers execute @@ -72,8 +81,7 @@ fn_final (void) TODO: Additional tests that we should do: 1. POSIX says we need to support at least ATEXIT_MAX - 2. Verify that fork'd child inherit the registrations of the parent. - 3. ... */ + 2. ... */ static int do_test (void) @@ -88,6 +96,40 @@ do_test (void) ATEXIT (fn1); ATEXIT (fn3); + /* Verify that handlers registered above are inherited across fork. */ + const pid_t child = fork (); + switch (child) + { + case -1: + printf ("fork: %m\n"); + _exit_with_flush (3); + case 0: /* Child. */ + break; + default: + { + int status; + const pid_t exited = waitpid (child, &status, 0); + if (child != exited) + { + printf ("unexpected child: %d, expected %d\n", exited, child); + _exit_with_flush (4); + } + if (status != 0) + { + if (WIFEXITED (status)) + printf ("unexpected exit status %d from child %d\n", + WEXITSTATUS (status), child); + else if (WIFSIGNALED (status)) + printf ("unexpected signal %d from child %d\n", + WTERMSIG (status), child); + else + printf ("unexpected status %d from child %d\n", status, child); + _exit_with_flush (5); + } + } + break; + } + EXIT (2); /* If we see this exit code, fn_final must have not worked. */ }