]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/isc/assertions.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / isc / assertions.c
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
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
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 *
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
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 }