Home | History | Annotate | Line # | Download | only in isc
      1 /*	$NetBSD: assertions.c,v 1.9 2025/01/26 16:25:36 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 
     21 #include <isc/assertions.h>
     22 #include <isc/backtrace.h>
     23 #include <isc/result.h>
     24 #include <isc/strerr.h>
     25 
     26 /*
     27  * The maximum number of stack frames to dump on assertion failure.
     28  */
     29 #ifndef BACKTRACE_MAXFRAME
     30 #define BACKTRACE_MAXFRAME 128
     31 #endif /* ifndef BACKTRACE_MAXFRAME */
     32 
     33 /*%
     34  * Forward.
     35  */
     36 static void
     37 default_callback(const char *, int, isc_assertiontype_t, const char *);
     38 
     39 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
     40 
     41 /*%
     42  * Public.
     43  */
     44 
     45 /*% assertion failed handler */
     46 /* coverity[+kill] */
     47 void
     48 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
     49 		     const char *cond) {
     50 	isc_assertion_failed_cb(file, line, type, cond);
     51 	abort();
     52 }
     53 
     54 /*% Set callback. */
     55 void
     56 isc_assertion_setcallback(isc_assertioncallback_t cb) {
     57 	if (cb == NULL) {
     58 		isc_assertion_failed_cb = default_callback;
     59 	} else {
     60 		isc_assertion_failed_cb = cb;
     61 	}
     62 }
     63 
     64 /*% Type to Text */
     65 const char *
     66 isc_assertion_typetotext(isc_assertiontype_t type) {
     67 	const char *result;
     68 
     69 	/*
     70 	 * These strings have purposefully not been internationalized
     71 	 * because they are considered to essentially be keywords of
     72 	 * the ISC development environment.
     73 	 */
     74 	switch (type) {
     75 	case isc_assertiontype_require:
     76 		result = "REQUIRE";
     77 		break;
     78 	case isc_assertiontype_ensure:
     79 		result = "ENSURE";
     80 		break;
     81 	case isc_assertiontype_insist:
     82 		result = "INSIST";
     83 		break;
     84 	case isc_assertiontype_invariant:
     85 		result = "INVARIANT";
     86 		break;
     87 	default:
     88 		result = "UNKNOWN";
     89 	}
     90 	return result;
     91 }
     92 
     93 /*
     94  * Private.
     95  */
     96 
     97 static void
     98 default_callback(const char *file, int line, isc_assertiontype_t type,
     99 		 const char *cond) {
    100 	void *tracebuf[ISC_BACKTRACE_MAXFRAME];
    101 	int nframes = isc_backtrace(tracebuf, ISC_BACKTRACE_MAXFRAME);
    102 
    103 	fprintf(stderr, "%s:%d: %s(%s) failed%s\n", file, line,
    104 		isc_assertion_typetotext(type), cond,
    105 		(nframes > 0) ? ", back trace" : ".");
    106 
    107 	if (nframes > 0) {
    108 		isc_backtrace_symbols_fd(tracebuf, nframes, fileno(stderr));
    109 	}
    110 
    111 	fflush(stderr);
    112 }
    113