#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <isc/atomic.h>
+#include <isc/backtrace.h>
#include <isc/hash.h>
#include <isc/magic.h>
#include <isc/mem.h>
* Private Inline-able.
*/
+static size_t
+total_inuse(void) {
+ size_t inuse = 0;
+ LOCK(&contextslock);
+ ISC_LIST_FOREACH(contexts, ctx, link) {
+ inuse += isc_mem_inuse(ctx);
+ }
+ UNLOCK(&contextslock);
+
+ return inuse;
+}
+
+static void
+write_string(int fd, const char *str) {
+ int r = write(fd, str, strlen(str));
+ if (r == -1) {
+ abort();
+ }
+}
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+static void
+write_size(int fd, size_t size) {
+ char buf[sizeof(TOSTRING(SIZE_MAX)) + 1] = { 0 };
+
+ char *str = buf + (sizeof(buf) - 1);
+
+ if (size == 0) {
+ *--str = '0';
+ } else {
+ while (size) {
+ *--str = '0' + (size % 10);
+ size /= 10;
+ }
+ }
+
+ write_string(fd, str);
+}
+#undef TOSTRING
+#undef STRINGIFY
+
+static void
+write_errno(int fd, int errnum) {
+ char buf[BUFSIZ] = { 0 };
+ int ret = isc_string_strerror_r(errnum, buf, sizeof(buf));
+ if (ret == 0) {
+ write_string(fd, buf);
+ }
+}
+
+static void
+write_backtrace(int fd) {
+ void *tracebuf[ISC_BACKTRACE_MAXFRAME];
+ int nframes = isc_backtrace(tracebuf, ISC_BACKTRACE_MAXFRAME);
+
+ if (nframes > 0) {
+ isc_backtrace_symbols_fd(tracebuf, nframes, fd);
+ }
+}
+
+#define CHECK_OOM(ptr, size) (void)((ptr != NULL) || (oom(size), false))
+
+ISC_NORETURN static void
+oom(size_t size) {
+ int fd = fileno(stderr);
+ write_string(fd, "Out of memory (trying to allocate ");
+ write_size(fd, size);
+ write_string(fd, ", total ");
+ write_size(fd, total_inuse());
+ write_string(fd, "): ");
+ write_errno(fd, errno);
+ write_string(fd, "\n");
+ write_backtrace(fd);
+
+ abort();
+}
+
#if !ISC_MEM_TRACKLINES
#define ADD_TRACE(mctx, ptr, size, func, file, line)
#define DELETE_TRACE(mctx, ptr, size, func, file, line)
idx = hash % DEBUG_TABLE_COUNT;
dl = mallocx(dlsize, mctx->jemalloc_flags);
- INSIST(dl != NULL);
+ CHECK_OOM(dl, dlsize);
ISC_LINK_INIT(dl, link);
dl->ptr = ptr;
*/
static void *
mem_get(isc_mem_t *ctx, size_t size, int flags) {
- char *ret = NULL;
-
ADJUST_ZERO_ALLOCATION_SIZE(size);
- ret = mallocx(size, flags | ctx->jemalloc_flags);
- INSIST(ret != NULL);
+ void *ptr = mallocx(size, flags | ctx->jemalloc_flags);
+ CHECK_OOM(ptr, size);
- return ret;
+ return ptr;
}
/*!
ADJUST_ZERO_ALLOCATION_SIZE(new_size);
new_ptr = rallocx(old_ptr, new_size, flags | ctx->jemalloc_flags);
- INSIST(new_ptr != NULL);
+ CHECK_OOM(new_ptr, new_size);
return new_ptr;
}
REQUIRE(name != NULL);
ctx = mallocx(sizeof(*ctx), jemalloc_flags);
- INSIST(ctx != NULL);
+ CHECK_OOM(ctx, sizeof(*ctx));
*ctx = (isc_mem_t){
.magic = MEM_MAGIC,
#if ISC_MEM_TRACKLINES
if ((ctx->debugging & ISC_MEM_DEBUGRECORD) != 0) {
unsigned int i;
+ size_t debuglist_size = ISC_CHECKED_MUL(DEBUG_TABLE_COUNT,
+ sizeof(debuglist_t));
- ctx->debuglist = mallocx(
- ISC_CHECKED_MUL(DEBUG_TABLE_COUNT, sizeof(debuglist_t)),
- jemalloc_flags);
- INSIST(ctx->debuglist != NULL);
+ ctx->debuglist = mallocx(debuglist_size, jemalloc_flags);
+ CHECK_OOM(ctx->debuglist, debuglist_size);
for (i = 0; i < DEBUG_TABLE_COUNT; i++) {
ISC_LIST_INIT(ctx->debuglist[i]);