diff --git a/CHANGES b/CHANGES index c29c72afba..8d89c6f8f3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4687. [func] Refactor tracklines code. [RT #45126] + 4686. [bug] dnssec-settime -p could print a bogus warning about key deletion scheduled before its inactivation when a key had an inactivation date set but no deletion date diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h index 8e8f7f7743..13f11e0e0c 100644 --- a/lib/isc/include/isc/mem.h +++ b/lib/isc/include/isc/mem.h @@ -745,6 +745,15 @@ isc__mem_register(void); * usually do not have to care about this function: it would call * isc_lib_register(), which internally calls this function. */ +void +isc__mem_printactive(isc_mem_t *mctx, FILE *file); +void +isc__mem_printallactive(FILE *file); +/*%< + * For internal use by the isc module and its unit tests, these functions + * print lists of active memory blocks for a single memory context or for + * all contexts. + */ ISC_LANG_ENDDECLS diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 68bb3b2bd9..e139429e61 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,7 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT; #define ALIGNMENT_SIZE 8U /*%< must be a power of 2 */ #define NUM_BASIC_BLOCKS 64 /*%< must be > 1 */ #define TABLE_INCREMENT 1024 -#define DEBUGLIST_COUNT 1024 +#define DEBUG_TABLE_COUNT 65536 /* * Types. @@ -59,13 +60,14 @@ typedef struct isc__mempool isc__mempool_t; typedef struct debuglink debuglink_t; struct debuglink { ISC_LINK(debuglink_t) link; - const void *ptr[DEBUGLIST_COUNT]; - size_t size[DEBUGLIST_COUNT]; - const char *file[DEBUGLIST_COUNT]; - unsigned int line[DEBUGLIST_COUNT]; - unsigned int count; + const void *ptr; + size_t size; + const char *file; + unsigned int line; }; +typedef ISC_LIST(debuglink_t) debuglist_t; + #define FLARG_PASS , file, line #define FLARG , const char *file, unsigned int line #else @@ -99,10 +101,6 @@ struct stats { #define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C') #define VALID_CONTEXT(c) ISC_MAGIC_VALID(c, MEM_MAGIC) -#if ISC_MEM_TRACKLINES -typedef ISC_LIST(debuglink_t) debuglist_t; -#endif - /* List of all active memory contexts. */ static ISC_LIST(isc__mem_t) contexts; @@ -158,7 +156,7 @@ struct isc__mem { #if ISC_MEM_TRACKLINES debuglist_t * debuglist; - unsigned int debuglistcnt; + size_t debuglistcnt; #endif unsigned int memalloc_failures; @@ -203,14 +201,14 @@ struct isc__mempool { #define TRACE_OR_RECORD (ISC_MEM_DEBUGTRACE|ISC_MEM_DEBUGRECORD) #define ADD_TRACE(a, b, c, d, e) \ do { \ - if ((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ - b != NULL) \ - add_trace_entry(a, b, c, d, e); \ + if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ + b != NULL)) \ + add_trace_entry(a, b, c, d, e); \ } while (0) #define DELETE_TRACE(a, b, c, d, e) \ do { \ - if ((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ - b != NULL) \ + if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ + b != NULL)) \ delete_trace_entry(a, b, c, d, e); \ } while(0) @@ -382,11 +380,11 @@ static struct isc__mempoolmethods { /*! * mctx must be locked. */ -static inline void +static void add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) { debuglink_t *dl; - unsigned int i; - size_t mysize = size; + isc_uint32_t hash; + isc_uint32_t idx; if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0) fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM, @@ -398,25 +396,18 @@ add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) { if (mctx->debuglist == NULL) return; - if (mysize > mctx->max_size) - mysize = mctx->max_size; + hash = isc_hash_function(&ptr, sizeof(ptr), ISC_TRUE, NULL); + idx = hash % DEBUG_TABLE_COUNT; - dl = ISC_LIST_HEAD(mctx->debuglist[mysize]); - while (dl != NULL) { - if (dl->count == DEBUGLIST_COUNT) - goto next; - for (i = 0; i < DEBUGLIST_COUNT; i++) { - if (dl->ptr[i] == NULL) { - dl->ptr[i] = ptr; - dl->size[i] = size; - dl->file[i] = file; - dl->line[i] = line; - dl->count++; - return; - } - } - next: - dl = ISC_LIST_NEXT(dl, link); + dl = ISC_LIST_TAIL(mctx->debuglist[idx]); + if (ISC_LIKELY(dl != NULL && dl->ptr == NULL)) { + ISC_LIST_UNLINK(mctx->debuglist[idx], dl, link); + dl->ptr = ptr; + dl->size = size; + dl->file = file; + dl->line = line; + ISC_LIST_PREPEND(mctx->debuglist[idx], dl, link); + return; } dl = malloc(sizeof(debuglink_t)); @@ -426,29 +417,22 @@ add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) { mctx->maxmalloced = mctx->malloced; ISC_LINK_INIT(dl, link); - for (i = 1; i < DEBUGLIST_COUNT; i++) { - dl->ptr[i] = NULL; - dl->size[i] = 0; - dl->file[i] = NULL; - dl->line[i] = 0; - } + dl->ptr = ptr; + dl->size = size; + dl->file = file; + dl->line = line; - dl->ptr[0] = ptr; - dl->size[0] = size; - dl->file[0] = file; - dl->line[0] = line; - dl->count = 1; - - ISC_LIST_PREPEND(mctx->debuglist[mysize], dl, link); + ISC_LIST_PREPEND(mctx->debuglist[idx], dl, link); mctx->debuglistcnt++; } -static inline void +static void delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size, const char *file, unsigned int line) { debuglink_t *dl; - unsigned int i; + isc_uint32_t hash; + isc_uint32_t idx; if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0) fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM, @@ -460,28 +444,19 @@ delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size, if (mctx->debuglist == NULL) return; - if (size > mctx->max_size) - size = mctx->max_size; + hash = isc_hash_function(&ptr, sizeof(ptr), ISC_TRUE, NULL); + idx = hash % DEBUG_TABLE_COUNT; - dl = ISC_LIST_HEAD(mctx->debuglist[size]); - while (dl != NULL) { - for (i = 0; i < DEBUGLIST_COUNT; i++) { - if (dl->ptr[i] == ptr) { - dl->ptr[i] = NULL; - dl->size[i] = 0; - dl->file[i] = NULL; - dl->line[i] = 0; - - INSIST(dl->count > 0); - dl->count--; - if (dl->count == 0) { - ISC_LIST_UNLINK(mctx->debuglist[size], - dl, link); - free(dl); - mctx->malloced -= sizeof(*dl); - } - return; - } + dl = ISC_LIST_HEAD(mctx->debuglist[idx]); + while (ISC_LIKELY(dl != NULL && dl->ptr != NULL)) { + if (ISC_UNLIKELY(dl->ptr == ptr)) { + ISC_LIST_UNLINK(mctx->debuglist[idx], dl, link); + dl->ptr = NULL; + dl->size = 0; + dl->file = NULL; + dl->line = 0; + ISC_LIST_APPEND(mctx->debuglist[idx], dl, link); + return; } dl = ISC_LIST_NEXT(dl, link); } @@ -490,7 +465,7 @@ delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size, * If we get here, we didn't find the item on the list. We're * screwed. */ - INSIST(dl != NULL); + INSIST(0); } #endif /* ISC_MEM_TRACKLINES */ @@ -1016,19 +991,19 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, } #if ISC_MEM_TRACKLINES - if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)) { unsigned int i; - ctx->debuglist = (memalloc)(arg, - (ctx->max_size+1) * sizeof(debuglist_t)); + ctx->debuglist = (memalloc)(arg, (DEBUG_TABLE_COUNT * + sizeof(debuglist_t))); if (ctx->debuglist == NULL) { result = ISC_R_NOMEMORY; goto error; } - for (i = 0; i <= ctx->max_size; i++) + for (i = 0; i < DEBUG_TABLE_COUNT; i++) ISC_LIST_INIT(ctx->debuglist[i]); - ctx->malloced += (ctx->max_size+1) * sizeof(debuglist_t); - ctx->maxmalloced += (ctx->max_size+1) * sizeof(debuglist_t); + ctx->malloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t); + ctx->maxmalloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t); } #endif @@ -1075,28 +1050,24 @@ destroy(isc__mem_t *ctx) { INSIST(ISC_LIST_EMPTY(ctx->pools)); #if ISC_MEM_TRACKLINES - if (ctx->debuglist != NULL) { - if (ctx->checkfree) { - for (i = 0; i <= ctx->max_size; i++) { - if (!ISC_LIST_EMPTY(ctx->debuglist[i])) + if (ISC_UNLIKELY(ctx->debuglist != NULL)) { + debuglink_t *dl; + for (i = 0; i < DEBUG_TABLE_COUNT; i++) + for (dl = ISC_LIST_HEAD(ctx->debuglist[i]); + dl != NULL; + dl = ISC_LIST_HEAD(ctx->debuglist[i])) { + if (ctx->checkfree && dl->ptr != NULL) print_active(ctx, stderr); - INSIST(ISC_LIST_EMPTY(ctx->debuglist[i])); - } - } else { - debuglink_t *dl; + INSIST (!ctx->checkfree || dl->ptr == NULL); + + ISC_LIST_UNLINK(ctx->debuglist[i], + dl, link); + free(dl); + ctx->malloced -= sizeof(*dl); + } - for (i = 0; i <= ctx->max_size; i++) - for (dl = ISC_LIST_HEAD(ctx->debuglist[i]); - dl != NULL; - dl = ISC_LIST_HEAD(ctx->debuglist[i])) { - ISC_LIST_UNLINK(ctx->debuglist[i], - dl, link); - free(dl); - ctx->malloced -= sizeof(*dl); - } - } (ctx->memfree)(ctx->arg, ctx->debuglist); - ctx->malloced -= (ctx->max_size+1) * sizeof(debuglist_t); + ctx->malloced -= DEBUG_TABLE_COUNT * sizeof(debuglist_t); } #endif INSIST(ctx->references == 0); @@ -1210,7 +1181,9 @@ isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { */ *ctxp = NULL; - if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & + (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)) + { if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) { si = &(((size_info *)ptr)[-1]); oldsize = si->u.size - ALIGNMENT_SIZE; @@ -1300,7 +1273,8 @@ isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) { REQUIRE(VALID_CONTEXT(ctx)); - if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) + if (ISC_UNLIKELY((isc_mem_debugging & + (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)) return (isc__mem_allocate(ctx0, size FLARG_PASS)); if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { @@ -1314,6 +1288,7 @@ isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) { } ADD_TRACE(ctx, ptr, size, file, line); + if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water) { ctx->is_overmem = ISC_TRUE; if (!ctx->hi_called) @@ -1344,7 +1319,9 @@ isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) { REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); - if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & + (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)) + { if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) { si = &(((size_info *)ptr)[-1]); oldsize = si->u.size - ALIGNMENT_SIZE; @@ -1403,7 +1380,7 @@ static void print_active(isc__mem_t *mctx, FILE *out) { if (mctx->debuglist != NULL) { debuglink_t *dl; - unsigned int i, j; + unsigned int i; const char *format; isc_boolean_t found; @@ -1415,23 +1392,21 @@ print_active(isc__mem_t *mctx, FILE *out) { format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM, ISC_MSG_PTRFILELINE, "\tptr %p size %u file %s line %u\n"); - for (i = 0; i <= mctx->max_size; i++) { + for (i = 0; i < DEBUG_TABLE_COUNT; i++) { dl = ISC_LIST_HEAD(mctx->debuglist[i]); if (dl != NULL) found = ISC_TRUE; while (dl != NULL) { - for (j = 0; j < DEBUGLIST_COUNT; j++) - if (dl->ptr[j] != NULL) - fprintf(out, format, - dl->ptr[j], - dl->size[j], - dl->file[j], - dl->line[j]); + if (dl->ptr != NULL) + fprintf(out, format, + dl->ptr, dl->size, + dl->file, dl->line); dl = ISC_LIST_NEXT(dl, link); } } + if (!found) fputs(isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM, ISC_MSG_NONE, "\tNone.\n"), out); @@ -1530,7 +1505,7 @@ mem_allocateunlocked(isc_mem_t *ctx0, size_t size) { size_info *si; size += ALIGNMENT_SIZE; - if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) + if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)) size += ALIGNMENT_SIZE; if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) @@ -1540,7 +1515,7 @@ mem_allocateunlocked(isc_mem_t *ctx0, size_t size) { if (si == NULL) return (NULL); - if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)) { si->u.ctx = ctx; si++; } @@ -1574,8 +1549,9 @@ isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) { } if (ctx->inuse > ctx->maxinuse) { ctx->maxinuse = ctx->inuse; - if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water && - (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0) + if (ISC_UNLIKELY(ctx->hi_water != 0U && + ctx->inuse > ctx->hi_water && + (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)) fprintf(stderr, "maxinuse = %lu\n", (unsigned long)ctx->inuse); } @@ -1612,7 +1588,9 @@ isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) { oldsize = (((size_info *)ptr)[-1]).u.size; INSIST(oldsize >= ALIGNMENT_SIZE); oldsize -= ALIGNMENT_SIZE; - if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & + ISC_MEM_DEBUGCTX) != 0)) + { INSIST(oldsize >= ALIGNMENT_SIZE); oldsize -= ALIGNMENT_SIZE; } @@ -1636,7 +1614,7 @@ isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) { REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); - if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)) { si = &(((size_info *)ptr)[-2]); REQUIRE(si->u.ctx == ctx); size = si[1].u.size; @@ -2084,7 +2062,9 @@ isc___mempool_get(isc_mempool_t *mpctx0 FLARG) { UNLOCK(mpctx->lock); #if ISC_MEM_TRACKLINES - if (((isc_mem_debugging & TRACE_OR_RECORD) != 0) && item != NULL) { + if (ISC_UNLIKELY(((isc_mem_debugging & TRACE_OR_RECORD) != 0) && + item != NULL)) + { MCTXLOCK(mctx, &mctx->lock); ADD_TRACE(mctx, item, mpctx->size, file, line); MCTXUNLOCK(mctx, &mctx->lock); @@ -2113,7 +2093,7 @@ isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) { mpctx->allocated--; #if ISC_MEM_TRACKLINES - if ((isc_mem_debugging & TRACE_OR_RECORD) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) { MCTXLOCK(mctx, &mctx->lock); DELETE_TRACE(mctx, mem, mpctx->size, file, line); MCTXUNLOCK(mctx, &mctx->lock); @@ -2343,7 +2323,7 @@ isc_mem_checkdestroyed(FILE *file) { LOCK(&contextslock); if (!ISC_LIST_EMPTY(contexts)) { #if ISC_MEM_TRACKLINES - if ((isc_mem_debugging & TRACE_OR_RECORD) != 0) { + if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) { isc__mem_t *ctx; for (ctx = ISC_LIST_HEAD(contexts); @@ -2415,7 +2395,7 @@ xml_renderctx(isc__mem_t *ctx, summarystat_t *summary, #if ISC_MEM_TRACKLINES if (ctx->debuglist != NULL) { summary->contextsize += - (ctx->max_size + 1) * sizeof(debuglist_t) + + DEBUG_TABLE_COUNT * sizeof(debuglist_t) + ctx->debuglistcnt * sizeof(debuglink_t); } #endif @@ -2601,7 +2581,7 @@ json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) { #if ISC_MEM_TRACKLINES if (ctx->debuglist != NULL) { summary->contextsize += - (ctx->max_size + 1) * sizeof(debuglist_t) + + DEBUG_TABLE_COUNT * sizeof(debuglist_t) + ctx->debuglistcnt * sizeof(debuglink_t); } #endif diff --git a/lib/isc/tests/mem_test.c b/lib/isc/tests/mem_test.c index b2ae459348..f6c67b9055 100644 --- a/lib/isc/tests/mem_test.c +++ b/lib/isc/tests/mem_test.c @@ -15,9 +15,11 @@ #include "isctest.h" +#include #include #include #include +#include static void * default_memalloc(void *arg, size_t size) { @@ -141,12 +143,160 @@ ATF_TC_BODY(isc_mem_inuse, tc) { isc_test_end(); } +#if ISC_MEM_TRACKLINES +ATF_TC(isc_mem_noflags); +ATF_TC_HEAD(isc_mem_noflags, tc) { + atf_tc_set_md_var(tc, "descr", "test mem with no flags"); +} + +ATF_TC_BODY(isc_mem_noflags, tc) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p, *q; + FILE *f; + void *ptr; + size_t size; + + result = isc_stdio_open("mem.output", "w", &f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_mem_createx2(0, 0, default_memalloc, default_memfree, + NULL, &mctx2, 0); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_mem_debugging = 0; + ptr = isc_mem_get(mctx2, 2048); + ATF_CHECK(ptr != NULL); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + result = isc_stdio_open("mem.output", "r", &f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, &size); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + p = strchr(buf, '\n'); + p += 2; + q = strchr(p, '\n'); + *q = '\0'; + ATF_CHECK_STREQ(p, "None."); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + isc_test_end(); + +} + +ATF_TC(isc_mem_recordflag); +ATF_TC_HEAD(isc_mem_recordflag, tc) { + atf_tc_set_md_var(tc, "descr", "test mem with record flag"); +} + +ATF_TC_BODY(isc_mem_recordflag, tc) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + size_t size; + + result = isc_stdio_open("mem.output", "w", &f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_mem_createx2(0, 0, default_memalloc, default_memfree, + NULL, &mctx2, 0); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ptr = isc_mem_get(mctx2, 2048); + ATF_CHECK(ptr != NULL); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + result = isc_stdio_open("mem.output", "r", &f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, &size); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + p = strchr(buf, '\n'); + ATF_CHECK(strncmp(p + 2, "ptr ", 4) == 0); + p = strchr(p + 1, '\n'); + ATF_CHECK(strlen(p) == 1); + + isc_test_end(); +} + +ATF_TC(isc_mem_traceflag); +ATF_TC_HEAD(isc_mem_traceflag, tc) { + atf_tc_set_md_var(tc, "descr", "test mem with trace flag"); +} + +ATF_TC_BODY(isc_mem_traceflag, tc) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + size_t size; + + /* redirect stderr so we can check trace output */ + f = freopen("mem.output", "w", stderr); + ATF_REQUIRE(f != NULL); + + result = isc_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_mem_createx2(0, 0, default_memalloc, default_memfree, + NULL, &mctx2, 0); + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ptr = isc_mem_get(mctx2, 2048); + ATF_CHECK(ptr != NULL); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + result = isc_stdio_open("mem.output", "r", &f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, &size); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + /* return stderr to TTY so we can see errors */ + f = freopen("/dev/tty", "w", stderr); + + ATF_CHECK(strncmp(buf, "add ", 4) == 0); + p = strchr(buf, '\n'); + p = strchr(p + 1, '\n'); + ATF_CHECK(strncmp(p + 2, "ptr ", 4) == 0); + p = strchr(p + 1, '\n'); + ATF_CHECK(strncmp(p + 1, "del ", 4) == 0); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + isc_test_end(); +} +#endif + /* * Main */ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, isc_mem_total); ATF_TP_ADD_TC(tp, isc_mem_inuse); +#if ISC_MEM_TRACKLINES + ATF_TP_ADD_TC(tp, isc_mem_noflags); + ATF_TP_ADD_TC(tp, isc_mem_recordflag); + ATF_TP_ADD_TC(tp, isc_mem_traceflag); +#endif return (atf_no_error()); }