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)
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
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
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
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