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