1272343Sngie/* $NetBSD: h_atexit.c,v 1.1 2010/07/16 15:42:53 jmmv Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2008 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie/* 30272343Sngie * Program to test atexit(3) and __cxa_atexit()/__cxa_finalize(). 31272343Sngie * 32272343Sngie * Written by Jason R. Thorpe, February 2003. 33272343Sngie * Public domain. 34272343Sngie */ 35272343Sngie 36272343Sngie#include <sys/cdefs.h> 37272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\ 38272343Sngie The NetBSD Foundation, inc. All rights reserved."); 39272343Sngie__RCSID("$NetBSD: h_atexit.c,v 1.1 2010/07/16 15:42:53 jmmv Exp $"); 40272343Sngie 41272343Sngie#include <stdio.h> 42272343Sngie#include <stdlib.h> 43272343Sngie#include <signal.h> 44272343Sngie#include <string.h> 45272343Sngie#include <unistd.h> 46272343Sngie 47272343Sngieextern int __cxa_atexit(void (*func)(void *), void *, void *); 48272343Sngieextern void __cxa_finalize(void *); 49272343Sngie 50274576Sngie#ifdef __FreeBSD__ 51274576Sngie/* 52274576Sngie * See comments in ../../lib/libc/stdlib/h_atexit.c about the deviation 53274576Sngie * between FreeBSD and NetBSD with this helper program 54274576Sngie */ 55274576Sngiestatic void *dso_handle_1 = (void *)1; 56274576Sngiestatic void *dso_handle_2 = (void *)2; 57274576Sngiestatic void *dso_handle_3 = (void *)3; 58274576Sngie#else 59272343Sngiestatic int dso_handle_1; 60272343Sngiestatic int dso_handle_2; 61272343Sngiestatic int dso_handle_3; 62274576Sngie#endif 63272343Sngie 64272343Sngiestatic int arg_1; 65272343Sngiestatic int arg_2; 66272343Sngiestatic int arg_3; 67272343Sngie 68272343Sngiestatic int exiting_state; 69272343Sngie 70272343Sngie#define ASSERT(expr) \ 71272343Sngiedo { \ 72272343Sngie if ((expr) == 0) { \ 73272343Sngie write(STDERR_FILENO, __func__, strlen(__func__)); \ 74272343Sngie write(STDERR_FILENO, ": ", 2); \ 75272343Sngie write(STDERR_FILENO, __STRING(expr), \ 76272343Sngie strlen(__STRING(expr))); \ 77272343Sngie write(STDERR_FILENO, "\n", 1); \ 78272343Sngie my_abort(); \ 79272343Sngie } \ 80272343Sngie} while (/*CONSTCOND*/0) 81272343Sngie 82272343Sngie#define SUCCESS() \ 83272343Sngiedo { \ 84272343Sngie write(STDOUT_FILENO, __func__, strlen(__func__)); \ 85272343Sngie write(STDOUT_FILENO, "\n", 1); \ 86272343Sngie} while (/*CONSTCOND*/0) 87272343Sngie 88272343Sngiestatic void 89272343Sngiemy_abort(void) 90272343Sngie{ 91272343Sngie 92272343Sngie kill(getpid(), SIGABRT); 93272343Sngie /* NOTREACHED */ 94272343Sngie} 95272343Sngie 96272343Sngiestatic void 97272343Sngiecxa_handler_5(void *arg) 98272343Sngie{ 99272343Sngie static int cxa_handler_5_called; 100272343Sngie 101272343Sngie ASSERT(arg == (void *)&arg_1); 102272343Sngie ASSERT(cxa_handler_5_called == 0); 103272343Sngie ASSERT(exiting_state == 5); 104272343Sngie 105272343Sngie exiting_state--; 106272343Sngie cxa_handler_5_called = 1; 107272343Sngie SUCCESS(); 108272343Sngie} 109272343Sngie 110272343Sngiestatic void 111272343Sngiecxa_handler_4(void *arg) 112272343Sngie{ 113272343Sngie static int cxa_handler_4_called; 114272343Sngie 115272343Sngie ASSERT(arg == (void *)&arg_1); 116272343Sngie ASSERT(cxa_handler_4_called == 0); 117272343Sngie ASSERT(exiting_state == 4); 118272343Sngie 119272343Sngie exiting_state--; 120272343Sngie cxa_handler_4_called = 1; 121272343Sngie SUCCESS(); 122272343Sngie} 123272343Sngie 124272343Sngiestatic void 125272343Sngiecxa_handler_3(void *arg) 126272343Sngie{ 127272343Sngie static int cxa_handler_3_called; 128272343Sngie 129272343Sngie ASSERT(arg == (void *)&arg_2); 130272343Sngie ASSERT(cxa_handler_3_called == 0); 131272343Sngie ASSERT(exiting_state == 3); 132272343Sngie 133272343Sngie exiting_state--; 134272343Sngie cxa_handler_3_called = 1; 135272343Sngie SUCCESS(); 136272343Sngie} 137272343Sngie 138272343Sngiestatic void 139272343Sngiecxa_handler_2(void *arg) 140272343Sngie{ 141272343Sngie static int cxa_handler_2_called; 142272343Sngie 143272343Sngie ASSERT(arg == (void *)&arg_3); 144272343Sngie ASSERT(cxa_handler_2_called == 0); 145272343Sngie ASSERT(exiting_state == 2); 146272343Sngie 147272343Sngie exiting_state--; 148272343Sngie cxa_handler_2_called = 1; 149272343Sngie SUCCESS(); 150272343Sngie} 151272343Sngie 152272343Sngiestatic void 153272343Sngienormal_handler_1(void) 154272343Sngie{ 155272343Sngie static int normal_handler_1_called; 156272343Sngie 157272343Sngie ASSERT(normal_handler_1_called == 0); 158272343Sngie ASSERT(exiting_state == 1); 159272343Sngie 160272343Sngie exiting_state--; 161272343Sngie normal_handler_1_called = 1; 162272343Sngie SUCCESS(); 163272343Sngie} 164272343Sngie 165272343Sngiestatic void 166272343Sngienormal_handler_0(void) 167272343Sngie{ 168272343Sngie static int normal_handler_0_called; 169272343Sngie 170272343Sngie ASSERT(normal_handler_0_called == 0); 171272343Sngie ASSERT(exiting_state == 0); 172272343Sngie 173272343Sngie normal_handler_0_called = 1; 174272343Sngie SUCCESS(); 175272343Sngie} 176272343Sngie 177272343Sngieint 178272343Sngiemain(int argc, char *argv[]) 179272343Sngie{ 180272343Sngie 181272343Sngie exiting_state = 5; 182272343Sngie 183274626Sngie#ifdef __FreeBSD__ 184272343Sngie ASSERT(0 == atexit(normal_handler_0)); 185272343Sngie ASSERT(0 == atexit(normal_handler_1)); 186274576Sngie ASSERT(0 == __cxa_atexit(cxa_handler_4, &arg_1, dso_handle_1)); 187274576Sngie ASSERT(0 == __cxa_atexit(cxa_handler_5, &arg_1, dso_handle_1)); 188274576Sngie ASSERT(0 == __cxa_atexit(cxa_handler_3, &arg_2, dso_handle_2)); 189274576Sngie ASSERT(0 == __cxa_atexit(cxa_handler_2, &arg_3, dso_handle_3)); 190274576Sngie 191274576Sngie __cxa_finalize(dso_handle_1); 192274576Sngie __cxa_finalize(dso_handle_2); 193274576Sngie#else 194272343Sngie ASSERT(0 == __cxa_atexit(cxa_handler_4, &arg_1, &dso_handle_1)); 195272343Sngie ASSERT(0 == __cxa_atexit(cxa_handler_5, &arg_1, &dso_handle_1)); 196272343Sngie ASSERT(0 == __cxa_atexit(cxa_handler_3, &arg_2, &dso_handle_2)); 197272343Sngie ASSERT(0 == __cxa_atexit(cxa_handler_2, &arg_3, &dso_handle_3)); 198272343Sngie 199272343Sngie __cxa_finalize(&dso_handle_1); 200272343Sngie __cxa_finalize(&dso_handle_2); 201274576Sngie#endif 202272343Sngie exit(0); 203272343Sngie} 204