-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unfinished task is resumed after co_main returns #198
Comments
I believe this is indeed an issue, caused by insufficiently destroyed coroutines. Please consider the following code: #include <boost/asio.hpp>
#include <boost/cobalt.hpp>
#include <iostream>
namespace ba = boost::asio;
namespace cobalt = boost::cobalt;
template <typename T1, typename T2>
cobalt::promise<void> delay(std::chrono::duration<T1, T2> d)
{
ba::system_timer tim{co_await cobalt::this_coro::executor, d};
co_await tim.async_wait(cobalt::use_op);
}
using namespace std::chrono;
cobalt::promise<void> co()
{
struct s{~s(){std::cout << "det" << std::endl; }} so{};
co_await delay(5ms);
}
cobalt::main co_main(int argc, char * argv[])
{
{
std::cout << "begin\n";
std::list<cobalt::promise<void>> l{};
l.emplace_back(delay(1ms));
l.emplace_back(co());
co_await race(l);
}
std::cout << "after\n";
co_return 0;
} expected output:
actual:
https://godbolt.org/z/PvonsEW3z thanks for taking care :) |
@neonxc No, your code shows expected behavior. There isn't a thing like an asynchronous destructor, therefore the async operation gets cancelled, but since it's unawaited the exception will leak. |
@nyibbang The task destructor doesn't trigger a cancel - so using a promise will work. |
Hello,
I've been using Cobalt with Boost 1.86.0, and I've had an issue with my code that caused it to segfault due to use of destroyed resources.
I've reproduced my issue on a smaller sample code:
I build this code with g++13 & libstdc++ on Ubuntu 22.04.
The output of this program is the following:
As we can see, the loop accesses the global flag after the
set_global_flag
object is destroyed (the flag is reset to 0), which means that the long_loop_task coroutine has been resumed after the co_main function returned. In this program, nothing much happens, but in my original code, the flag was a pointer passed by reference to the loop and theset_global_flag
was aunique_ptr
, which caused the loop to access through the reference an object that was destroyed.The program never terminates, even if an interrupt (Ctrl+C) or termination (SIGTERM) signal is sent. I have to kill it with a SIGKILL or SIGQUIT.
I understand that according to
cobalt::race
specification, the loop task should not be cancelled, because it is passed by lvalue-reference. It is however surprising to me that it is resumed though, even after the task object was destroyed.Am I missing something ?
Thank you in advance.
The text was updated successfully, but these errors were encountered: