Not strictly necessary, but it may help ASAN and remove some false positives.
Sadly, this annotation produces an ASAN error: $ tests/test-coroutine -p /basic/lifecycle /basic/lifecycle: ==27655==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases! ==27655==AddressSanitizer CHECK failed: /builddir/build/BUILD/compiler-rt-4.0.1.src/lib/asan/asan_poisoning.cc:38 "((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0) #0 0x55d1e4e8a695 in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/home/elmarco/src/qq/build/tests/test-coroutine+0x1c0695) #1 0x55d1e4ea6235 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/home/elmarco/src/qq/build/tests/test-coroutine+0x1dc235) #2 0x55d1e4e82ea4 in __asan::PoisonShadow(unsigned long, unsigned long, unsigned char) (/home/elmarco/src/qq/build/tests/test-coroutine+0x1b8ea4) #3 0x55d1e4dde1e7 in __asan::FakeStack::Destroy(int) (/home/elmarco/src/qq/build/tests/test-coroutine+0x1141e7) #4 0x55d1e528b775 in qemu_coroutine_switch /home/elmarco/src/qq/util/coroutine-ucontext.c:219:9 #5 0x55d1e528b18d in coroutine_trampoline /home/elmarco/src/qq/util/coroutine-ucontext.c:114:9 #6 0x7fb3e0087bef (/lib64/libc.so.6+0x50bef) Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- util/coroutine-ucontext.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index 6621f3f692..d200498c38 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -31,6 +31,25 @@ #include <valgrind/valgrind.h> #endif +#if (defined(__has_feature) && __has_feature(address_sanitizer)) || \ + __SANITIZE_ADDRESS__ +#include <sanitizer/asan_interface.h> +#else +/* stub to check correct arguments */ +static inline void +__sanitizer_start_switch_fiber(void **fake_stack_save, + const void *bottom, size_t size) +{ +} + +static inline void +__sanitizer_finish_switch_fiber(void *fake_stack_save, + const void **bottom_old, + size_t *size_old) +{ +} +#endif + typedef struct { Coroutine base; void *stack; @@ -64,6 +83,15 @@ static void coroutine_trampoline(int i0, int i1) union cc_arg arg; CoroutineUContext *self; Coroutine *co; + const void *bottom_old; + size_t size_old; + void *fake_stack_save; + + __sanitizer_finish_switch_fiber(NULL, &bottom_old, &size_old); + if (!leader.stack) { + leader.stack = (void *)bottom_old; + leader.stack_size = size_old; + } arg.i[0] = i0; arg.i[1] = i1; @@ -72,9 +100,14 @@ static void coroutine_trampoline(int i0, int i1) /* Initialize longjmp environment and switch back the caller */ if (!sigsetjmp(self->env, 0)) { + __sanitizer_start_switch_fiber(&fake_stack_save, + bottom_old, size_old); siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); } + __sanitizer_finish_switch_fiber(&fake_stack_save, + NULL, NULL); + while (true) { co->entry(co->entry_arg); qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE); @@ -87,6 +120,7 @@ Coroutine *qemu_coroutine_new(void) ucontext_t old_uc, uc; sigjmp_buf old_env; union cc_arg arg = {0}; + void *fake_stack_save; /* The ucontext functions preserve signal masks which incurs a * system call overhead. sigsetjmp(buf, 0)/siglongjmp() does not @@ -122,8 +156,13 @@ Coroutine *qemu_coroutine_new(void) /* swapcontext() in, siglongjmp() back out */ if (!sigsetjmp(old_env, 0)) { + __sanitizer_start_switch_fiber(&fake_stack_save, + co->stack, co->stack_size); swapcontext(&old_uc, &uc); } + + __sanitizer_finish_switch_fiber(&fake_stack_save, NULL, NULL); + return &co->base; } @@ -169,13 +208,21 @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_); CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_); int ret; + void *fake_stack_save; current = to_; ret = sigsetjmp(from->env, 0); if (ret == 0) { + + __sanitizer_start_switch_fiber(action == COROUTINE_TERMINATE ? + NULL : &fake_stack_save, + to->stack, to->stack_size); siglongjmp(to->env, action); } + + __sanitizer_finish_switch_fiber(&fake_stack_save, NULL, NULL); + return ret; } -- 2.15.1.355.g36791d7216