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
isc_assertion_failed(const char * file,int line,isc_assertiontype_t type,const char * cond)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
isc_assertion_setcallback(isc_assertioncallback_t cb)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 *
isc_assertion_typetotext(isc_assertiontype_t type)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
default_callback(const char * file,int line,isc_assertiontype_t type,const char * cond)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