Skip to content

Fix ASan stack range registration for main task#3298

Open
chenBright wants to merge 1 commit into
apache:masterfrom
chenBright:fix_bthread_exit_asan
Open

Fix ASan stack range registration for main task#3298
chenBright wants to merge 1 commit into
apache:masterfrom
chenBright:fix_bthread_exit_asan

Conversation

@chenBright
Copy link
Copy Markdown
Contributor

@chenBright chenBright commented May 13, 2026

What problem does this PR solve?

Issue Number: resolve

Problem Summary:

Under ASan, every bthread_exit from a non-main task (i.e. the
throw bthread::ExitException(retval) branch) reliably emits the
following warning to stderr, polluting test output and confusing future
ASan reports:

==42417==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x7feebb8cc000; bottom 0x7feebc8c9000; size: 0xffffffffff003000 (-16764928)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189

(top - bottom ≈ 1.5 GiB is impossible for any real stack: brpc's
biggest bthread stack is STACK_TYPE_LARGE, an order-of-magnitude
smaller, and a default pthread stack is only a few MB.)

Root cause: brpc's StackStorage::bottom is, by convention, the
highest address of the stack (see bthread/stack.h comment "Assume
stack grows upwards"; stack.cpp confirms with
s->bottom = (char*)mem + stacksize). However, in the ASan-only branch
of TaskGroup::init, the value passed to stk->storage.bottom for the
main task came straight from PthreadAttrGetStack, which on Linux uses
pthread_attr_getstack(3) — and that returns the lowest address of
the region. The convention was therefore violated for the main task.

internal::StartSwitchFiber computes
asan_stack_bottom = (char*)storage.bottom - storage.stacksize and
passes it to __sanitizer_start_switch_fiber. With the convention
violated, this address was stacksize bytes below the real pthread
stack, so the per-jump BTHREAD_SCOPED_ASAN_FIBER_SWITCHER told ASan
that the main task lives in nonsensical memory. From that point on,
ASan's per-thread fake-stack tracking was inconsistent with reality.
The first time the C++ unwinder fired (e.g. from
throw bthread::ExitException), __asan_handle_no_return saw a stack
range that straddles the bthread stack and the bogus "main" stack and
bailed out with the warning above.

What is changed and the side effects?

Changed:

PthreadAttrGetStack now translates
the lowest address returned by pthread_attr_getstack(3) into a
highest address before returning, so callers can keep treating the
output as a StackStorage::bottom. macOS already returns the stack
base (highest address) via pthread_get_stackaddr_np(3) and is
unchanged. A comment is added describing the convention.

Before fix:

[ RUN      ] BthreadTest.bthread_exit
I0510 08:26:19.082902 42422 210453414407 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0510 08:26:19.083010 42427 214748387572 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0510 08:26:19.083033 42426 141733932703 bthread_unittest.cpp:125 just_exit] just_exit(0)
==42417==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x7feebb8cc000; bottom 0x7feebc8c9000; size: 0xffffffffff003000 (-16764928)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
I0510 08:26:19.083066 42422 176093685563 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0510 08:26:19.083850 42431     0 bthread_unittest.cpp:125 just_exit] just_exit(0)
[       OK ] BthreadTest.bthread_exit (1 ms)

After fix:

[ RUN      ] BthreadTest.bthread_exit
I0513 14:07:54.980260 42664 193273544132 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0513 14:07:54.980327 42668 236223216497 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0513 14:07:54.980370 42670 266287994733 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0513 14:07:54.980438 42664 210453406139 bthread_unittest.cpp:125 just_exit] just_exit(0)
I0513 14:07:54.980901 42671     0 bthread_unittest.cpp:125 just_exit] just_exit(0)
[       OK ] BthreadTest.bthread_exit (1 ms)

Side effects:

  • Performance effects:

  • Breaking backward compatibility:


Check List:

…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.
@chenBright chenBright changed the title Fix ASan stack range registration for main task to silence "ignoring requested __asan_handle_no_return" Fix ASan stack range registration for main task May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant