about summary refs log tree commit diff
path: root/stdlib/tst-atexit-common.c
blob: 262235a478556fb8b6c2445a6228c4d18f864a04 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* Helper file for tst-{atexit,at_quick_exit,cxa_atexit,on_exit}.
   Copyright (C) 2017 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>

#define MAX_ATEXIT 20  /* Large enough for current set of invocations.  */
static char crumbs[MAX_ATEXIT];
static int next_slot = 0;

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)
{
  /* Arbitrary sequence matching current registrations.  */
  const char expected[] = "3021121130211";

  if (strcmp (crumbs, expected) == 0)
    _exit (0);

  printf ("crumbs:   %s\n", crumbs);
  printf ("expected: %s\n", expected);
  _exit (1);
}

/* This is currently just a basic test to verify that exit handlers execute
   in LIFO order, even when the handlers register additional new handlers.

   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. ...  */

static int
do_test (void)
{
  /* Register this first so it can verify expected order of the rest.  */
  ATEXIT (fn_final);

  ATEXIT (fn1);
  ATEXIT (fn3);
  ATEXIT (fn1);
  ATEXIT (fn2);
  ATEXIT (fn1);
  ATEXIT (fn3);

  EXIT (2);  /* If we see this exit code, fn_final must have not worked.  */
}

#define TEST_FUNCTION do_test
#include <support/test-driver.c>