diff --git a/cmake/CompileBoost.cmake b/cmake/CompileBoost.cmake index fab1c5706b..9e7fbd2971 100644 --- a/cmake/CompileBoost.cmake +++ b/cmake/CompileBoost.cmake @@ -62,8 +62,13 @@ if(USE_SANITIZER) message(FATAL_ERROR "Sanitizers are not supported on Windows") endif() message(STATUS "A sanitizer is enabled, need to build boost from source") - compile_boost(TARGET boost_asan BUILD_ARGS context-impl=ucontext - CXXFLAGS ${SANITIZER_COMPILE_OPTIONS} LDFLAGS ${SANITIZER_LINK_OPTIONS}) + if (USE_VALGRIND) + compile_boost(TARGET boost_asan BUILD_ARGS valgrind=on + CXXFLAGS ${SANITIZER_COMPILE_OPTIONS} LDFLAGS ${SANITIZER_LINK_OPTIONS}) + else() + compile_boost(TARGET boost_asan BUILD_ARGS context-impl=ucontext + CXXFLAGS ${SANITIZER_COMPILE_OPTIONS} LDFLAGS ${SANITIZER_LINK_OPTIONS}) + endif() return() endif() diff --git a/cmake/ConfigureCompiler.cmake b/cmake/ConfigureCompiler.cmake index 80d7cfee26..4dbe9db816 100644 --- a/cmake/ConfigureCompiler.cmake +++ b/cmake/ConfigureCompiler.cmake @@ -168,7 +168,10 @@ else() if(NOT CLANG) message(FATAL_ERROR "Unsupported configuration: USE_MSAN only works with Clang") endif() - list(APPEND SANITIZER_COMPILE_OPTIONS -fsanitize=memory -fsanitize-memory-track-origins=2) + list(APPEND SANITIZER_COMPILE_OPTIONS + -fsanitize=memory + -fsanitize-memory-track-origins=2 + -DBOOST_USE_UCONTEXT) list(APPEND SANITIZER_LINK_OPTIONS -fsanitize=memory) endif() @@ -180,23 +183,25 @@ else() list(APPEND SANITIZER_COMPILE_OPTIONS -fsanitize=undefined # TODO(atn34) Re-enable -fsanitize=alignment once https://github.com/apple/foundationdb/issues/1434 is resolved - -fno-sanitize=alignment) + -fno-sanitize=alignment + -DBOOST_USE_UCONTEXT) list(APPEND SANITIZER_LINK_OPTIONS -fsanitize=undefined) endif() if(USE_TSAN) - list(APPEND SANITIZER_COMPILE_OPTIONS -fsanitize=thread) + list(APPEND SANITIZER_COMPILE_OPTIONS -fsanitize=thread -DBOOST_USE_UCONTEXT) list(APPEND SANITIZER_LINK_OPTIONS -fsanitize=thread) endif() - set(USE_SANITIZER OFF) + if(USE_VALGRIND) + list(APPEND SANITIZER_COMPILE_OPTIONS -DBOOST_USE_VALGRIND) + endif() + if(SANITIZER_COMPILE_OPTIONS) add_compile_options(${SANITIZER_COMPILE_OPTIONS}) - set(USE_SANITIZER ON) endif() if(SANITIZER_LINK_OPTIONS) add_link_options(${SANITIZER_LINK_OPTIONS}) - set(USE_SANITIZER ON) endif() if(PORTABLE_BINARY) diff --git a/cmake/FDBComponents.cmake b/cmake/FDBComponents.cmake index 6204a5d6f6..bfde36f2ee 100644 --- a/cmake/FDBComponents.cmake +++ b/cmake/FDBComponents.cmake @@ -97,6 +97,10 @@ if(GO_EXECUTABLE AND NOT WIN32) else() set(WITH_GO OFF) endif() +if (USE_SANITIZER) + # Disable building go for sanitizers, since _stacktester doesn't link properly + set(WITH_GO OFF) +endif() ################################################################################ # Ruby diff --git a/fdbserver/CoroFlow.actor.cpp b/fdbserver/CoroFlow.actor.cpp index fba65d2ed8..8e84e8ad61 100644 --- a/fdbserver/CoroFlow.actor.cpp +++ b/fdbserver/CoroFlow.actor.cpp @@ -63,12 +63,18 @@ struct Coroutine /*: IThreadlike*/ { void unblock() { //Coro_switchTo_( swapCoro(coro), coro ); - blocked.send(Void()); + + // Copy blocked before calling send, since the call to send might destroy it. + auto b = blocked; + b.send(Void()); } - void send(Future const& what) { - (*sink)(what); + void waitFor(Future const& what) { + ASSERT(current_coro == this); + current_coro = nullptr; + (*sink)(what); // Pass control back to the switcher actor ASSERT(what.isReady()); + current_coro = this; } protected: @@ -80,10 +86,7 @@ protected: } catch (Error& e) { // We just want to transfer control back to the coroutine. The coroutine will handle the error. } - current_coro = self; - (*self->coro)(); // Transfer control to the coroutine, and wait until the coroutine has a future it needs to - // wait for - current_coro = nullptr; + (*self->coro)(); // Transfer control to the coroutine. This call "returns" after waitFor is called. wait(delay(0, g_network->getCurrentTask())); } } @@ -105,10 +108,10 @@ protected: virtual void run() = 0; private: - std::unique_ptr coro; coro_t::push_type* sink; Promise blocked; std::shared_ptr alive{ std::make_shared(true) }; + std::unique_ptr coro; }; template @@ -285,9 +288,8 @@ void CoroThreadPool::waitFor( Future what ) { ASSERT(current_coro != nullptr); if (what.isReady()) return; // double t = now(); - auto c = current_coro; - current_coro = nullptr; - c->send(what); + current_coro->waitFor(what); + what.get(); // Throw if |what| is an error } // Right After INet2::run