From c0e151d1125f6a0a54d9a92890d2798e659922f8 Mon Sep 17 00:00:00 2001 From: chenBright Date: Wed, 13 May 2026 21:47:43 +0800 Subject: [PATCH] Fix ASan stack range registration for main task to silence "ignoring requested __asan_handle_no_return" On Linux, `pthread_attr_getstack(3)` returns the lowest address of the stack, but brpc treats `StackStorage::bottom` as the highest address (see `bthread/stack.h`). `TaskGroup::init` was registering the main task's stack with the lowest address as `bottom`, so every per-jump `BTHREAD_SCOPED_ASAN_FIBER_SWITCHER` told ASan a stack range `stacksize` bytes below the real one. The first `__asan_handle_no_return` (e.g. the C++ unwinder fired by `throw bthread::ExitException` inside `bthread_exit`) then prints WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: ...; bottom ...; size: 0x62bdb000 (~1.5 GiB) False positive error reports may follow Fix `PthreadAttrGetStack` to translate the lowest address to the highest address before returning, matching `StackStorage::bottom`. ASan-only path; non-ASan builds are unaffected. --- src/bthread/bthread.cpp | 7 ------- src/bthread/task_group.cpp | 12 +++++++++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/bthread/bthread.cpp b/src/bthread/bthread.cpp index 27ded27acd..9b0f45991d 100644 --- a/src/bthread/bthread.cpp +++ b/src/bthread/bthread.cpp @@ -396,13 +396,6 @@ int bthread_equal(bthread_t t1, bthread_t t2) { return t1 == t2; } -#ifdef BUTIL_USE_ASAN -// Fixme!!! -// The noreturn `bthread_exit' may cause a warning of ASan, but does not abort the program. -// -// ==94463==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x00016dd7f000; bottom 0x00010b1a4000; size: 0x000062bdb000 (1656598528) -// False positive error reports may follow -#endif // BUTIL_USE_ASAN void bthread_exit(void* retval) { bthread::TaskGroup* g = bthread::tls_task_group; if (g != NULL && !g->is_current_main_task()) { diff --git a/src/bthread/task_group.cpp b/src/bthread/task_group.cpp index 579bb23120..4eea7f986a 100644 --- a/src/bthread/task_group.cpp +++ b/src/bthread/task_group.cpp @@ -247,6 +247,12 @@ TaskGroup::~TaskGroup() { } #ifdef BUTIL_USE_ASAN +// Returns the **highest** address of the calling pthread's stack and its +// total size, matching brpc's `StackStorage::bottom` convention (see comment +// in bthread/stack.h: "Assume stack grows upwards"). Note that on Linux +// `pthread_attr_getstack(3)` returns the lowest address of the region, so +// we have to translate it; on macOS `pthread_get_stackaddr_np(3)` already +// returns the stack base (highest address), so we use it as-is. int PthreadAttrGetStack(void*& stack_addr, size_t& stack_size) { #if defined(OS_MACOSX) stack_addr = pthread_get_stackaddr_np(pthread_self()); @@ -259,9 +265,13 @@ int PthreadAttrGetStack(void*& stack_addr, size_t& stack_size) { LOG(ERROR) << "Fail to get pthread attributes: " << berror(rc); return rc; } - rc = pthread_attr_getstack(&attr, &stack_addr, &stack_size); + void* stack_lowest = NULL; + rc = pthread_attr_getstack(&attr, &stack_lowest, &stack_size); if (0 != rc) { LOG(ERROR) << "Fail to get pthread stack: " << berror(rc); + } else { + // Translate lowest -> highest to match StackStorage::bottom. + stack_addr = (char*)stack_lowest + stack_size; } pthread_attr_destroy(&attr); return rc;