coroutine stack overflows
- Dominant language
- C++
- Stars
- 30.5k
- Forks
- 5.9k
- PR merge metrics
- No merged PRs in 30d
Description
The stack of this unit test overflows.
```
class UnitTest_FollyCoro : public ::testing::Test {
public:
folly::coro::Task task40(int index) {
std::cout << index << std::endl;
co_return 40;
}
folly::coro::Task many_subtasks() {
for (auto i = 0; i < 100000; i ++) {
co_await task40(i); // Call task40 many times
}
co_return 0;
}
};
TEST_F(UnitTest_FollyCoro, many_subtasks) {
folly::coro::blockingWait(many_subtasks());
}
```
The stack shown VS Code is that `task40` and `many_subtasks` repeat themselves, and details here.
```
......UnitTest_FollyCoro::task40(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame *)(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame * frame_ptr) (....../FollyCoroTest.cpp:76)
......UnitTest_FollyCoro::many_subtasks(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame *)(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame * frame_ptr) (....../FollyCoroTest.cpp:79)
......UnitTest_FollyCoro::task40(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame *)(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame * frame_ptr) (....../FollyCoroTest.cpp:74)
......UnitTest_FollyCoro::many_subtasks(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame *)(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame * frame_ptr) (....../FollyCoroTest.cpp:79)
......UnitTest_FollyCoro::task40(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame *)(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame * frame_ptr) (....../FollyCoroTest.cpp:74)
......UnitTest_FollyCoro::many_subtasks(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame *)(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame * frame_ptr) (....../FollyCoroTest.cpp:79)
......UnitTest_FollyCoro::task40(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame *)(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame * frame_ptr) (....../FollyCoroTest.cpp:74)
......UnitTest_FollyCoro::many_subtasks(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame *)(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame * frame_ptr) (....../FollyCoroTest.cpp:79)
......UnitTest_FollyCoro::task40(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame *)(_ZN8......18UnitTest_FollyCoro6task40Ei.Frame * frame_ptr) (....../FollyCoroTest.cpp:74)
......UnitTest_FollyCoro::many_subtasks(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame *)(_ZN8......18UnitTest_FollyCoro13many_subtasksEv.Frame * frame_ptr) (....../FollyCoroTest.cpp:79)
folly::coro::detail::makeRefBlockingWaitTask(_ZN5folly4coro6detail23makeRefBlockingWaitTaskINS0_4TaskIiE7AwaiterEiLi0EEENS1_16BlockingWaitTaskINSt20add_lvalue_referenceIT0_E4typeEEEOT_.Frame *)(_ZN5folly4coro6detail23makeRefBlockingWaitTaskINS0_4TaskIiE7AwaiterEiLi0EEENS1_16BlockingWaitTaskINSt20add_lvalue_referenceIT0_E4typeEEEOT_.Frame * frame_ptr) (....../folly/folly/experimental/coro/BlockingWait.h:294)
std::__n4861::coroutine_handle::resume(const std::__n4861::coroutine_handle * const this) (/usr/include/c++/11/coroutine:126)
folly::resumeCoroutineWithNewAsyncStackRoot(std::__n4861::coroutine_handle h, folly::AsyncStackFrame & frame) (....../folly/folly/tracing/AsyncStack.cpp:179)
folly::resumeCoroutineWithNewAsyncStackRoot >(std::__n4861::coroutine_handle > h) (....../folly/folly/tracing/AsyncStack-inl.h:88)
folly::coro::detail::BlockingWaitTask::getVia(folly::DrivableExecutor*, folly::AsyncStackFrame&) &&::{lambda()#1}::operator()()(struct {...} * const __closure) (....../folly/folly/experimental/coro/BlockingWait.h:232)
folly::detail::function::FunctionTraits::callSmall::getVia(folly::DrivableExecutor*, folly::AsyncStackFrame&) &&::{lambda()#1}>(folly::detail::function::Data&)(folly::detail::function::Data & p) (....../folly/folly/Function.h:345)
folly::detail::function::FunctionTraits::operator()()(folly::detail::function::FunctionTraits * const this) (....../folly/folly/Function.h:374)
folly::coro::detail::BlockingWaitExecutor::drive()::{lambda()#1}::operator()() const(const struct {...} * const __closure) (....../folly/folly/experimental/coro/BlockingWait.h:327)
folly::fibers::(anonymous namespace)::runNoInline >(struct {...} &&)(struct {...} && func) (....../folly/folly/fibers/FiberManagerInternal-inl.h:49)
folly::fibers::runInMainContext(folly::coro::detail::BlockingWaitExecutor::drive()::{lambda()#1}&&)(struct {...} && func) (....../folly/folly/fibers/FiberManagerInternal-inl.h:635)
```
I did the same test with `cppcoro` (https://github.com/lewissbaker/cppcoro) library, and the stack does **not** overflow.
```
class UnitTest_cppcoro_task : public ::testing::Test {
public:
cppcoro::task task40(int index) {
std::cout << index << std::endl;
co_return 40;
}
cppcoro::task many_subtasks() {
for (auto i = 0; i < 10000000; i ++) {
co_await task40(i);
}
co_return 0;
}
};
TEST_F(UnitTest_cppcoro_task, many_subtasks) {
cppcoro::sync_wait(many_subtasks());
}
```
Contributor guide
Assessment
This issue has not been assessed yet.