1 /* 2 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1997-2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* $Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp $ */ 19 20 /*! \file */ 21 22 #include <config.h> 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #include <isc/assertions.h> 28 #include <isc/backtrace.h> 29 #include <isc/msgs.h> 30 #include <isc/result.h> 31 32 /* 33 * The maximum number of stack frames to dump on assertion failure. 34 */ 35 #ifndef BACKTRACE_MAXFRAME 36 #define BACKTRACE_MAXFRAME 128 37 #endif 38 39 /*% 40 * Forward. 41 */ 42 static void 43 default_callback(const char *, int, isc_assertiontype_t, const char *); 44 45 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback; 46 47 /*% 48 * Public. 49 */ 50 51 /*% assertion failed handler */ 52 /* coverity[+kill] */ 53 void 54 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type, 55 const char *cond) 56 { 57 isc_assertion_failed_cb(file, line, type, cond); 58 abort(); 59 /* NOTREACHED */ 60 } 61 62 /*% Set callback. */ 63 void 64 isc_assertion_setcallback(isc_assertioncallback_t cb) { 65 if (cb == NULL) 66 isc_assertion_failed_cb = default_callback; 67 else 68 isc_assertion_failed_cb = cb; 69 } 70 71 /*% Type to Text */ 72 const char * 73 isc_assertion_typetotext(isc_assertiontype_t type) { 74 const char *result; 75 76 /* 77 * These strings have purposefully not been internationalized 78 * because they are considered to essentially be keywords of 79 * the ISC development environment. 80 */ 81 switch (type) { 82 case isc_assertiontype_require: 83 result = "REQUIRE"; 84 break; 85 case isc_assertiontype_ensure: 86 result = "ENSURE"; 87 break; 88 case isc_assertiontype_insist: 89 result = "INSIST"; 90 break; 91 case isc_assertiontype_invariant: 92 result = "INVARIANT"; 93 break; 94 default: 95 result = NULL; 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