2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-27 20:49:04 +00:00
bind/lib/isc/assertions.c
Tony Finch 295e7c80e8 Ad-hoc backtrace logging with isc_backtrace_log()
It's sometimes helpful to get a quick idea of the call stack when
debugging. This change factors out the backtrace logging from named's
fatal error handler so that it's easy to use in other places too.
2023-03-29 10:47:53 +00:00

111 lines
2.4 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <stdio.h>
#include <stdlib.h>
#include <isc/assertions.h>
#include <isc/backtrace.h>
#include <isc/result.h>
#include <isc/strerr.h>
/*
* The maximum number of stack frames to dump on assertion failure.
*/
#ifndef BACKTRACE_MAXFRAME
#define BACKTRACE_MAXFRAME 128
#endif /* ifndef BACKTRACE_MAXFRAME */
/*%
* Forward.
*/
static void
default_callback(const char *, int, isc_assertiontype_t, const char *);
static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
/*%
* Public.
*/
/*% assertion failed handler */
/* coverity[+kill] */
void
isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
const char *cond) {
isc_assertion_failed_cb(file, line, type, cond);
abort();
}
/*% Set callback. */
void
isc_assertion_setcallback(isc_assertioncallback_t cb) {
if (cb == NULL) {
isc_assertion_failed_cb = default_callback;
} else {
isc_assertion_failed_cb = cb;
}
}
/*% Type to Text */
const char *
isc_assertion_typetotext(isc_assertiontype_t type) {
const char *result;
/*
* These strings have purposefully not been internationalized
* because they are considered to essentially be keywords of
* the ISC development environment.
*/
switch (type) {
case isc_assertiontype_require:
result = "REQUIRE";
break;
case isc_assertiontype_ensure:
result = "ENSURE";
break;
case isc_assertiontype_insist:
result = "INSIST";
break;
case isc_assertiontype_invariant:
result = "INVARIANT";
break;
default:
result = "UNKNOWN";
}
return (result);
}
/*
* Private.
*/
static void
default_callback(const char *file, int line, isc_assertiontype_t type,
const char *cond) {
void *tracebuf[ISC_BACKTRACE_MAXFRAME];
int nframes = isc_backtrace(tracebuf, ISC_BACKTRACE_MAXFRAME);
fprintf(stderr, "%s:%d: %s(%s) failed%s\n", file, line,
isc_assertion_typetotext(type), cond,
(nframes > 0) ? ", back trace" : ".");
if (nframes > 0) {
isc_backtrace_symbols_fd(tracebuf, nframes, fileno(stderr));
}
fflush(stderr);
}