Skip to content

Commit 64203d5

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 64203d5

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

include/seastar/core/coroutine.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
#include <coroutine>
3333
#endif
3434

35+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ > 15 || (__GNUC__ == 15 && __GNUC_MINOR__ >= 2))
36+
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121961
37+
#define SEATAR_INTERNAL_DESTROY_HANDLE_IN_SUSPEND_BROKEN 1
38+
#endif
39+
3540
namespace seastar {
3641

3742
namespace internal {

include/seastar/coroutine/exception.hh

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

4444
template<typename U>
4545
void await_suspend(std::coroutine_handle<U> hndl) noexcept {
46+
#ifdef SEATAR_INTERNAL_DESTROY_HANDLE_IN_SUSPEND_BROKEN
47+
schedule(new lambda_task([hndl, eptr = std::move(eptr)] () mutable {
48+
#endif
4649
hndl.promise().set_exception(std::move(eptr));
4750
hndl.destroy();
51+
#ifdef SEATAR_INTERNAL_DESTROY_HANDLE_IN_SUSPEND_BROKEN
52+
}));
53+
#endif
4854
}
4955

5056
void await_resume() noexcept {}

0 commit comments

Comments
 (0)