123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- /* Helper file for tst-{atexit,at_quick_exit,cxa_atexit,on_exit}.
- Copyright (C) 2017-2019 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
- #include <assert.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/wait.h>
- /* http://pubs.opengroup.org/onlinepubs/000095399/functions/atexit.html
- requires that we support at least 32 atexit handlers.
- The number we actually support is limited by memory. Here we simply
- check that we support at least the minimum required. */
- #define MAX_ATEXIT 32
- /* Arbitrary sequence matching current registrations. */
- const char expected[] = "00000000000000000000000003021121130211";
- static char crumbs[sizeof (expected)];
- 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)
- {
- crumbs[next_slot++] = '0';
- }
- static void
- fn1 (void)
- {
- crumbs[next_slot++] = '1';
- }
- static void
- fn2 (void)
- {
- crumbs[next_slot++] = '2';
- ATEXIT (fn1);
- }
- static void
- fn3 (void)
- {
- crumbs[next_slot++] = '3';
- ATEXIT (fn2);
- ATEXIT (fn0);
- }
- static void
- fn_final (void)
- {
- if (strcmp (crumbs, expected) == 0)
- _exit_with_flush (0);
- printf ("crumbs: %s\n", crumbs);
- printf ("expected: %s\n", expected);
- _exit_with_flush (1);
- }
- static int
- do_test (void)
- {
- int slots_remaining = MAX_ATEXIT;
- /* Register this first so it can verify expected order of the rest. */
- ATEXIT (fn_final); --slots_remaining;
- ATEXIT (fn1); --slots_remaining;
- ATEXIT (fn3); --slots_remaining;
- ATEXIT (fn1); --slots_remaining;
- ATEXIT (fn2); --slots_remaining;
- ATEXIT (fn1); --slots_remaining;
- ATEXIT (fn3); --slots_remaining;
- /* Fill the rest of available slots with fn0. */
- while (slots_remaining > 0)
- {
- ATEXIT (fn0); --slots_remaining;
- }
- /* 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. */
- }
- #define TEST_FUNCTION do_test
- #include <support/test-driver.c>
|