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