From 4adf78e10717bcfbefb9d5690a39a2db08f34c7f Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Mon, 31 Aug 2026 17:25:42 +0000 Subject: [PATCH] trace2: remove use of ALLOC_GROW() The ALLOC_GROW() helper can call die() on a failed memory allocation. We need to remove this from the trace2 API code to prevent a recursive die() handler. This helper is used to track the nested region stack. Use a new skipped_regions member to track how many times a region was entered without being added to the stack, and decrease that amount as we leave each region. This allows us to avoid a failure and instead stop deepening the stack, giving as much nesting behavior as possible without failing the entire process. Helped-by: Elijah Newren Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- banned-die.h | 3 +++ trace2/tr2_tls.c | 34 +++++++++++++++++++++++++++++++++- trace2/tr2_tls.h | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/banned-die.h b/banned-die.h index 4d1800353d..cff1072397 100644 --- a/banned-die.h +++ b/banned-die.h @@ -23,4 +23,7 @@ #undef ALLOC_ARRAY #define ALLOC_ARRAY(x, alloc) BANNED(ALLOC_ARRAY) +#undef ALLOC_GROW +#define ALLOC_GROW(x, nr, alloc) BANNED(ALLOC_GROW) + #endif /* BANNED_DIE_H */ diff --git a/trace2/tr2_tls.c b/trace2/tr2_tls.c index 49bd505d62..5e4624d0b3 100644 --- a/trace2/tr2_tls.c +++ b/trace2/tr2_tls.c @@ -109,8 +109,33 @@ void tr2tls_unset_self(void) void tr2tls_push_self(uint64_t us_now) { struct tr2tls_thread_ctx *ctx = tr2tls_get_self(); + uint64_t *new_array; + size_t new_alloc; + + if (ctx->nr_skipped_regions) { + ctx->nr_skipped_regions++; + return; + } + + if (ctx->nr_open_regions >= ctx->alloc) { + if (ctx->alloc > + SIZE_MAX / (2 * sizeof(*ctx->array_us_start))) { + ctx->nr_skipped_regions++; + return; + } + new_alloc = ctx->alloc * 2; + + new_array = realloc(ctx->array_us_start, + new_alloc * sizeof(*ctx->array_us_start)); + if (!new_array) { + ctx->nr_skipped_regions++; + return; + } + + ctx->array_us_start = new_array; + ctx->alloc = new_alloc; + } - ALLOC_GROW(ctx->array_us_start, ctx->nr_open_regions + 1, ctx->alloc); ctx->array_us_start[ctx->nr_open_regions++] = us_now; } @@ -118,6 +143,11 @@ void tr2tls_pop_self(void) { struct tr2tls_thread_ctx *ctx = tr2tls_get_self(); + if (ctx->nr_skipped_regions) { + ctx->nr_skipped_regions--; + return; + } + if (!ctx->nr_open_regions) BUG("no open regions in thread '%s'", ctx->thread_name); @@ -138,6 +168,8 @@ uint64_t tr2tls_region_elasped_self(uint64_t us) uint64_t us_start; ctx = tr2tls_get_self(); + if (ctx->nr_skipped_regions) + return 0; if (!ctx->nr_open_regions) return 0; diff --git a/trace2/tr2_tls.h b/trace2/tr2_tls.h index 3bdbf4d275..c365017923 100644 --- a/trace2/tr2_tls.h +++ b/trace2/tr2_tls.h @@ -20,6 +20,7 @@ struct tr2tls_thread_ctx { uint64_t *array_us_start; size_t alloc; size_t nr_open_regions; /* plays role of "nr" in ALLOC_GROW */ + size_t nr_skipped_regions; int thread_id; struct tr2_timer_block timer_block; struct tr2_counter_block counter_block;