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