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