Is it valid to call handle.destroy()
from within the final suspension of a C++ coroutine?
From my understanding, this should be fine because the coroutine is currently suspended and it won't be resumed again.
Still, AddressSanitizer reports a heap-use-after-free
for the following code snippet:
#include <experimental/coroutine>
#include <iostream>
using namespace std;
struct final_awaitable {
bool await_ready() noexcept { return false; }
void await_resume() noexcept {}
template<typename PROMISE> std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle<PROMISE> coro) noexcept {
coro.destroy(); // Is this valid?
return std::experimental::noop_coroutine();
}
};
struct task {
struct promise_type;
using coro_handle = std::experimental::coroutine_handle<promise_type>;
struct promise_type {
task get_return_object() { return {}; }
auto initial_suspend() { return std::experimental::suspend_never(); }
auto final_suspend() noexcept { return final_awaitable(); }
void unhandled_exception() { std::terminate(); }
void return_void() {}
};
};
task foo() {
cerr << "foo\n";
co_return;
}
int main() {
auto x = foo();
}
when compiled with clang 11.0.1 and the compilation flags -stdlib=libc++ --std=c++17 -fcoroutines-ts -fno-exceptions -fsanitize=address
. (see https://godbolt.org/z/eq6eoc)
(simplified version of my actual code. You can find the complete code in https://godbolt.org/z/8Yadv1)
Is this an issue in my code or a wrong positive in AddressSanitizer?