1 /* $NetBSD: assertions.c,v 1.4 2024/08/19 08:28:32 martin Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1997-2001 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp */ 21 22 /*! \file */ 23 24 #include <config.h> 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 29 #include <isc/assertions.h> 30 #include <isc/backtrace.h> 31 #include <isc/msgs.h> 32 #include <isc/result.h> 33 34 /* 35 * The maximum number of stack frames to dump on assertion failure. 36 */ 37 #ifndef BACKTRACE_MAXFRAME 38 #define BACKTRACE_MAXFRAME 128 39 #endif 40 41 /*% 42 * Forward. 43 */ 44 static void 45 default_callback(const char *, int, isc_assertiontype_t, const char *); 46 47 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback; 48 49 /*% 50 * Public. 51 */ 52 53 /*% assertion failed handler */ 54 /* coverity[+kill] */ 55 void 56 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type, 57 const char *cond) 58 { 59 isc_assertion_failed_cb(file, line, type, cond); 60 abort(); 61 /* NOTREACHED */ 62 } 63 64 /*% Set callback. */ 65 void 66 isc_assertion_setcallback(isc_assertioncallback_t cb) { 67 if (cb == NULL) 68 isc_assertion_failed_cb = default_callback; 69 else 70 isc_assertion_failed_cb = cb; 71 } 72 73 /*% Type to Text */ 74 const char * 75 isc_assertion_typetotext(isc_assertiontype_t type) { 76 const char *result = "?"; 77 78 /* 79 * These strings have purposefully not been internationalized 80 * because they are considered to essentially be keywords of 81 * the ISC development environment. 82 */ 83 switch (type) { 84 case isc_assertiontype_require: 85 result = "REQUIRE"; 86 break; 87 case isc_assertiontype_ensure: 88 result = "ENSURE"; 89 break; 90 case isc_assertiontype_insist: 91 result = "INSIST"; 92 break; 93 case isc_assertiontype_invariant: 94 result = "INVARIANT"; 95 break; 96 } 97 return (result); 98 } 99 100 /* 101 * Private. 102 */ 103 104 static void 105 default_callback(const char *file, int line, isc_assertiontype_t type, 106 const char *cond) 107 { 108 void *tracebuf[BACKTRACE_MAXFRAME]; 109 int i, nframes; 110 const char *logsuffix = "."; 111 const char *fname; 112 isc_result_t result; 113 114 result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); 115 if (result == ISC_R_SUCCESS && nframes > 0) 116 logsuffix = ", back trace"; 117 118 fprintf(stderr, "%s:%d: %s(%s) %s%s\n", 119 file, line, isc_assertion_typetotext(type), cond, 120 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, 121 ISC_MSG_FAILED, "failed"), logsuffix); 122 if (result == ISC_R_SUCCESS) { 123 for (i = 0; i < nframes; i++) { 124 unsigned long offset; 125 126 fname = NULL; 127 result = isc_backtrace_getsymbol(tracebuf[i], &fname, 128 &offset); 129 if (result == ISC_R_SUCCESS) { 130 fprintf(stderr, "#%d %p in %s()+0x%lx\n", i, 131 tracebuf[i], fname, offset); 132 } else { 133 fprintf(stderr, "#%d %p in ??\n", i, 134 tracebuf[i]); 135 } 136 } 137 } 138 fflush(stderr); 139 } 140