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