Skip to content

Commit 6d16dc4

Browse files
committed
coroutine: exception: workaround broken destroy coroutine handle in await_suspend
gcc 15.2 and above crash if a coroutine handle is destroyed when await_suspend for that coroutine is called [1]. An internal reference counter is accessed after the coroutine is destroyed. Work around this by scheduling the work to a task. This is slower, but doesn't crash, and exceptions are supposed to be somewhat rare. [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121961
1 parent 99e07a1 commit 6d16dc4

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

include/seastar/core/coroutine.hh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ namespace seastar {
3636

3737
namespace internal {
3838

39+
40+
inline
41+
void
42+
execute_involving_handle_destruction_in_await_suspend(std::invocable<> auto&& func) noexcept {
43+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ > 15 || (__GNUC__ == 15 && __GNUC_MINOR__ >= 2))
44+
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121961
45+
memory::scoped_critical_alloc_section _;
46+
schedule(new lambda_task(std::forward<decltype(func)>(func)));
47+
#else
48+
std::invoke(std::forward<decltype(func)>(func));
49+
#endif
50+
}
51+
52+
3953
template <typename T = void>
4054
class coroutine_traits_base {
4155
public:

include/seastar/coroutine/exception.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ struct exception_awaiter {
4343

4444
template<typename U>
4545
void await_suspend(std::coroutine_handle<U> hndl) noexcept {
46+
execute_involving_handle_destruction_in_await_suspend([hndl, eptr = std::move(eptr)] () mutable {
4647
hndl.promise().set_exception(std::move(eptr));
4748
hndl.destroy();
49+
});
4850
}
4951

5052
void await_resume() noexcept {}

0 commit comments

Comments
 (0)