1*ee9ce107SKyle Evans /* 2*ee9ce107SKyle Evans * Copyright (C) 2025 Kyle Evans <kevans@FreeBSD.org> 3*ee9ce107SKyle Evans * 4*ee9ce107SKyle Evans * SPDX-License-Identifier: BSD-2-Clause 5*ee9ce107SKyle Evans * 6*ee9ce107SKyle Evans */ 7*ee9ce107SKyle Evans 8*ee9ce107SKyle Evans #include <unistd.h> 9*ee9ce107SKyle Evans 10*ee9ce107SKyle Evans static int exit_code = -1; 11*ee9ce107SKyle Evans static bool fatal_atexit; 12*ee9ce107SKyle Evans 13*ee9ce107SKyle Evans extern "C" { 14*ee9ce107SKyle Evans void set_fatal_atexit(bool); 15*ee9ce107SKyle Evans void set_exit_code(int); 16*ee9ce107SKyle Evans } 17*ee9ce107SKyle Evans 18*ee9ce107SKyle Evans void set_fatal_atexit(bool fexit)19*ee9ce107SKyle Evansset_fatal_atexit(bool fexit) 20*ee9ce107SKyle Evans { 21*ee9ce107SKyle Evans fatal_atexit = fexit; 22*ee9ce107SKyle Evans } 23*ee9ce107SKyle Evans 24*ee9ce107SKyle Evans void set_exit_code(int code)25*ee9ce107SKyle Evansset_exit_code(int code) 26*ee9ce107SKyle Evans { 27*ee9ce107SKyle Evans exit_code = code; 28*ee9ce107SKyle Evans } 29*ee9ce107SKyle Evans 30*ee9ce107SKyle Evans struct other_object { ~other_objectother_object31*ee9ce107SKyle Evans ~other_object() { 32*ee9ce107SKyle Evans 33*ee9ce107SKyle Evans /* 34*ee9ce107SKyle Evans * In previous versions of our __cxa_atexit handling, we would 35*ee9ce107SKyle Evans * never actually execute this handler because it's added during 36*ee9ce107SKyle Evans * ~object() below; __cxa_finalize would never revisit it. We 37*ee9ce107SKyle Evans * will allow the caller to configure us to exit with a certain 38*ee9ce107SKyle Evans * exit code so that it can run us twice: once to ensure we 39*ee9ce107SKyle Evans * don't crash at the end, and again to make sure the handler 40*ee9ce107SKyle Evans * actually ran. 41*ee9ce107SKyle Evans */ 42*ee9ce107SKyle Evans if (exit_code != -1) 43*ee9ce107SKyle Evans _exit(exit_code); 44*ee9ce107SKyle Evans } 45*ee9ce107SKyle Evans }; 46*ee9ce107SKyle Evans 47*ee9ce107SKyle Evans void create_staticobj()48*ee9ce107SKyle Evanscreate_staticobj() 49*ee9ce107SKyle Evans { 50*ee9ce107SKyle Evans static other_object obj; 51*ee9ce107SKyle Evans } 52*ee9ce107SKyle Evans 53*ee9ce107SKyle Evans struct object { ~objectobject54*ee9ce107SKyle Evans ~object() { 55*ee9ce107SKyle Evans /* 56*ee9ce107SKyle Evans * If we're doing the fatal_atexit behavior (i.e., create an 57*ee9ce107SKyle Evans * object that will add its own dtor for __cxa_finalize), then 58*ee9ce107SKyle Evans * we don't exit here. 59*ee9ce107SKyle Evans */ 60*ee9ce107SKyle Evans if (fatal_atexit) 61*ee9ce107SKyle Evans create_staticobj(); 62*ee9ce107SKyle Evans else if (exit_code != -1) 63*ee9ce107SKyle Evans _exit(exit_code); 64*ee9ce107SKyle Evans } 65*ee9ce107SKyle Evans }; 66*ee9ce107SKyle Evans 67*ee9ce107SKyle Evans static object obj; 68