1258945Sroberto/* 2280849Scy * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1997-2001 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file */ 21258945Sroberto 22258945Sroberto#include <config.h> 23258945Sroberto 24258945Sroberto#include <stdio.h> 25258945Sroberto#include <stdlib.h> 26258945Sroberto 27258945Sroberto#include <isc/assertions.h> 28280849Scy#include <isc/backtrace.h> 29258945Sroberto#include <isc/msgs.h> 30280849Scy#include <isc/result.h> 31258945Sroberto 32280849Scy/* 33280849Scy * The maximum number of stack frames to dump on assertion failure. 34280849Scy */ 35280849Scy#ifndef BACKTRACE_MAXFRAME 36280849Scy#define BACKTRACE_MAXFRAME 128 37280849Scy#endif 38280849Scy 39258945Sroberto/*% 40258945Sroberto * Forward. 41258945Sroberto */ 42258945Srobertostatic void 43258945Srobertodefault_callback(const char *, int, isc_assertiontype_t, const char *); 44258945Sroberto 45280849Scystatic isc_assertioncallback_t isc_assertion_failed_cb = default_callback; 46280849Scy 47258945Sroberto/*% 48258945Sroberto * Public. 49258945Sroberto */ 50258945Sroberto 51280849Scy/*% assertion failed handler */ 52280849Scy/* coverity[+kill] */ 53280849Scyvoid 54280849Scyisc_assertion_failed(const char *file, int line, isc_assertiontype_t type, 55280849Scy const char *cond) 56280849Scy{ 57280849Scy isc_assertion_failed_cb(file, line, type, cond); 58280849Scy abort(); 59280849Scy /* NOTREACHED */ 60280849Scy} 61258945Sroberto 62258945Sroberto/*% Set callback. */ 63258945Srobertovoid 64258945Srobertoisc_assertion_setcallback(isc_assertioncallback_t cb) { 65258945Sroberto if (cb == NULL) 66280849Scy isc_assertion_failed_cb = default_callback; 67258945Sroberto else 68280849Scy isc_assertion_failed_cb = cb; 69258945Sroberto} 70258945Sroberto 71258945Sroberto/*% Type to Text */ 72258945Srobertoconst char * 73258945Srobertoisc_assertion_typetotext(isc_assertiontype_t type) { 74258945Sroberto const char *result; 75258945Sroberto 76258945Sroberto /* 77258945Sroberto * These strings have purposefully not been internationalized 78258945Sroberto * because they are considered to essentially be keywords of 79258945Sroberto * the ISC development environment. 80258945Sroberto */ 81258945Sroberto switch (type) { 82258945Sroberto case isc_assertiontype_require: 83258945Sroberto result = "REQUIRE"; 84258945Sroberto break; 85258945Sroberto case isc_assertiontype_ensure: 86258945Sroberto result = "ENSURE"; 87258945Sroberto break; 88258945Sroberto case isc_assertiontype_insist: 89258945Sroberto result = "INSIST"; 90258945Sroberto break; 91258945Sroberto case isc_assertiontype_invariant: 92258945Sroberto result = "INVARIANT"; 93258945Sroberto break; 94258945Sroberto default: 95258945Sroberto result = NULL; 96258945Sroberto } 97258945Sroberto return (result); 98258945Sroberto} 99258945Sroberto 100258945Sroberto/* 101258945Sroberto * Private. 102258945Sroberto */ 103258945Sroberto 104258945Srobertostatic void 105258945Srobertodefault_callback(const char *file, int line, isc_assertiontype_t type, 106258945Sroberto const char *cond) 107258945Sroberto{ 108280849Scy void *tracebuf[BACKTRACE_MAXFRAME]; 109280849Scy int i, nframes; 110280849Scy const char *logsuffix = "."; 111280849Scy const char *fname; 112280849Scy isc_result_t result; 113280849Scy 114280849Scy result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); 115280849Scy if (result == ISC_R_SUCCESS && nframes > 0) 116280849Scy logsuffix = ", back trace"; 117280849Scy 118280849Scy fprintf(stderr, "%s:%d: %s(%s) %s%s\n", 119258945Sroberto file, line, isc_assertion_typetotext(type), cond, 120258945Sroberto isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, 121280849Scy ISC_MSG_FAILED, "failed"), logsuffix); 122280849Scy if (result == ISC_R_SUCCESS) { 123280849Scy for (i = 0; i < nframes; i++) { 124280849Scy unsigned long offset; 125280849Scy 126280849Scy fname = NULL; 127280849Scy result = isc_backtrace_getsymbol(tracebuf[i], &fname, 128280849Scy &offset); 129280849Scy if (result == ISC_R_SUCCESS) { 130280849Scy fprintf(stderr, "#%d %p in %s()+0x%lx\n", i, 131280849Scy tracebuf[i], fname, offset); 132280849Scy } else { 133280849Scy fprintf(stderr, "#%d %p in ??\n", i, 134280849Scy tracebuf[i]); 135280849Scy } 136280849Scy } 137280849Scy } 138258945Sroberto fflush(stderr); 139258945Sroberto} 140