由于 boost::asio::co_spawn 如何通过 io_context::run 传播,异常消失了

问题描述 投票:0回答:1

在协程之前,当从回调中抛出异常时,例如通过

boost::asio::post
,异常将从
boost::asio::io_context::run()
传播出去。然而,如果通过
boost::asio::co_spawn
使用协程,在像
boost::asio::detached
这样的即发即忘模式下,异常不会从
run()
中抛出。在类似的问题中,一个答案,https://stackoverflow.com/a/68042350/3537677,提到使用带有
void (std::exception_ptr,...)
签名的完成处理程序,但是我根本无法在该处理程序中执行代码。

那么如何从 co_routines 中获取异常并传播到

io_context::run
,或者如果不可能的话,如何定义一个异常处理子句,即到
co_spawn
我的 MRE

#include <iostream>
#include <boost/asio.hpp>

boost::asio::awaitable<void>  coroutine() {
    std::cout << "Coroutine executes...\n";
    throw std::runtime_error("Test throw from coroutine!");
    co_return;
}

int main(int argc, char* argv[]) {
    boost::asio::io_context context;

    boost::asio::co_spawn(context, coroutine(), boost::asio::detached);
    boost::asio::co_spawn(context, coroutine(), [] (std::exception_ptr ptr) {
        std::cout << "Rethrowing in completion handler\n"; //Doesn't get executed
        throw ptr;
    });

    boost::asio::post(context, [] () {
        throw std::runtime_error("Test throw from post!");
    });

    std::thread t([&context]() {
        try {
            while (true) {
                context.run();
                return;
            }
        } catch (std::exception &e) {
            std::cerr << "Exception in context::run(): " << e.what() << "\n";
        }
    });
    t.join();
}

实际产量:

Coroutine executes...
Coroutine executes...
Exception in context::run(): Test throw from post!

Process finished with exit code 0

所需输出:

...
Coroutine executes...
std::cout << "Rethrowing in completion handler\n";
Exception in context::run(): Test throw from coroutine!
Exception in context::run(): Test throw from post!
Process finished with exit code 0
c++ boost boost-asio c++-coroutine boost-coroutine
1个回答
0
投票

throw ptr
并没有像你想象的那样做。

使用

if (ptr) {
    std::cout << "Rethrowing in completion handler" << std::endl;
    std::rethrow_exception(ptr);
}

接下来,处理

io_context
的异常略有不同:您提前停止
io_context

稍微简化和改进输出:

实时编译器资源管理器

#include <iostream>
#include <boost/asio.hpp>

boost::asio::awaitable<void> coroutine() {
    std::cout << "Coroutine executes..." << std::endl;
    throw std::runtime_error("Test throw from coroutine!");
    co_return;
}

int main() {
    boost::asio::io_context context;

    boost::asio::co_spawn(context, coroutine, boost::asio::detached);
    boost::asio::co_spawn(context, coroutine, [](std::exception_ptr ptr) {
        if (ptr) {
            std::cout << "Rethrowing in completion handler" << std::endl;
            std::rethrow_exception(ptr);
        } else {
            std::cout << "Completed without error" << std::endl;
        }
    });

    boost::asio::post(context, [] { throw std::runtime_error("Test throw from post!"); });

    while (true) {
        try {
            context.run();
            break;
        } catch (std::exception const& e) {
            std::cerr << "Exception in context::run(): " << e.what() << std::endl;
        }
    }
}

打印

Coroutine executes...
Coroutine executes...
Exception in context::run(): Test throw from post!
Rethrowing in completion handler
Exception in context::run(): Test throw from coroutine!
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.