1 /* $OpenBSD: atexit_test.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */
2
3 /*
4 * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <dlfcn.h>
20 #include <err.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 void *libaa, *libab;
25
26 #define CALLBACK(name) static void name(void) { printf("exe "#name"\n"); }
27
28 CALLBACK(cleanup1)
CALLBACK(cleanup2)29 CALLBACK(cleanup2)
30 CALLBACK(cleanup3)
31
32 static void
33 cleanup_dlclose(void)
34 {
35 printf("exe cleanup_dlclose begin\n");
36 dlclose(libaa);
37 dlclose(libab);
38 printf("exe cleanup_dlclose end\n");
39 }
40
41 static void
aa(void)42 aa(void)
43 {
44 void (*func)(void) = dlsym(libaa, "aa");
45 if (func == NULL)
46 errx(1, "dlsym(libaa, aa): %s", dlerror());
47 func();
48 }
49
50 static void
ab(void)51 ab(void)
52 {
53 void (*func)(void) = dlsym(libab, "ab");
54 if (func == NULL)
55 errx(1, "dlsym(libab, ab): %s", dlerror());
56 func();
57 }
58
59 int
main(int argc,char ** argv)60 main(int argc, char **argv)
61 {
62 int test;
63
64 libaa = dlopen(LIBAA, RTLD_LAZY);
65 if (libaa == NULL)
66 errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAA, dlerror());
67
68 libab = dlopen(LIBAB, RTLD_LAZY);
69 if (libab == NULL)
70 errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAB, dlerror());
71
72 if (argc != 2)
73 test = 0;
74 else
75 test = atoi(argv[1]);
76
77 switch (test) {
78 case 0:
79 /* 1, aa, 2, ab, 3, then exit */
80 atexit(cleanup1);
81 aa();
82 atexit(cleanup2);
83 ab();
84 atexit(cleanup3);
85 exit(0);
86
87 case 1:
88 /* 1, aa, 2, ab, 3, then dlclose aa, then bb */
89 atexit(cleanup1);
90 aa();
91 atexit(cleanup2);
92 ab();
93 atexit(cleanup3);
94 dlclose(libaa);
95 dlclose(libab);
96 exit(0);
97
98 case 2:
99 /* 1, aa, cleanup_dlclose, ab, 3, then exit */
100 atexit(cleanup1);
101 aa();
102 atexit(cleanup_dlclose);
103 ab();
104 atexit(cleanup3);
105 exit(0);
106
107 case 3:
108 /* 1, aa, 2, ab, cleanup_dlclose, then exit */
109 atexit(cleanup1);
110 aa();
111 atexit(cleanup2);
112 ab();
113 atexit(cleanup_dlclose);
114 exit(0);
115
116 }
117
118 return (0);
119 }
120