xref: /freebsd/contrib/ntp/libntp/lib/isc/assertions.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
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