Opened 4 years ago

#13570 new Bugs

asio_handler_invoke resume wrong thread in coroutine

Reported by: pengying.wu@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.67.0 Severity: Problem
Keywords: asio, coroutine, asio_handler_invoke Cc:

Description

Environment:
Windows 10, VS2015 Update3, Boost 1.65.1, Boost 1.67.0, x86/x64

Coroutine should be suspended and resumed by the same thread, but in boost 1.67.0 it doesn't. I guess it's a bug introduced since boost 1.66.

In Boost 1.65.0, correct behavior, output:
thread : 37c0
thread : 37c0
hello

In Boost 1.67.0, wrong behavior, output:
thread : df4
thread : 1844
hello

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

std::string Test(boost::asio::io_service& ios, 
    boost::asio::yield_context yield)
{
    boost::asio::io_service::work work(ios);

#if BOOST_VERSION >= 106600
    boost::asio::async_completion<
        boost::asio::yield_context,
        void(boost::system::error_code, std::string)>
        init(BOOST_ASIO_MOVE_CAST(boost::asio::yield_context)(yield));
    auto handler = init.completion_handler;

#else 
    boost::asio::detail::async_result_init<
        boost::asio::yield_context, 
        void(boost::system::error_code, std::string)>
        init(BOOST_ASIO_MOVE_CAST(boost::asio::yield_context)(yield));
    auto handler = init.handler;
#endif

    boost::thread t([&handler]() {
    
        boost::this_thread::sleep_for(boost::chrono::seconds(2));
        boost::asio::detail::asio_handler_invoke(
            boost::bind<void>(
                handler, boost::system::error_code(), "hello"), &handler);

    });
    t.detach();
    
    return init.result.get();

}

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

    boost::asio::spawn(ios, [&ios](boost::asio::yield_context yield) {

        boost::system::error_code ec;
        std::cout << "thread : " << boost::this_thread::get_id() << std::endl;
        std::string msg = Test(ios, yield[ec]);
        std::cout << "thread : " << boost::this_thread::get_id() << std::endl;
        std::cout << msg << std::endl;

    });

    ios.run();

    std::string tmp;
    std::cin >> tmp;

    return 0;

}

Change History (0)

Note: See TracTickets for help on using tickets.