Skip to content

ip::tcp::socket::async_write_some hangs in coroutine when remote endpoint is closed #1720

@ffranzoni

Description

@ffranzoni

Version of Boost

1.88.0.

Actual and Expected Behavior

I am testing the behavior of an ip::tcp::socket (created by a call to ip::tcp::acceptor::async_accept) after the remote endpoint has closed the connection. What I expect is that any async_write_some call done on the local socket subsequent to ip::tcp::socket::close done by the remote socket should either return or fail with a Broken Pipe exception. Since I need to use coroutines, I am calling async_write_some with the use_awaitable Completion Token.

This is my code, written as a test case for Google Test:

TEST_F(TCPTest, CloseSocket)
{
    using namespace boost::asio;

    thread_pool         pool{1};
    const ip::address   myAddress{ip::make_address("127.0.0.1")};
    const ip::port_type myPort{54'321};

    ip::tcp::acceptor acceptor(pool.get_executor(), ip::tcp::endpoint{myAddress, myPort});

    ip::tcp::socket socket{pool.get_executor()};
    socket.connect(ip::tcp::endpoint{myAddress, myPort});

    auto acceptedSock = acceptor.async_accept(use_future).get();

    socket.close();
    
    const auto writeFunc{[](ip::tcp::socket& sock) -> awaitable<void> {
        const std::string message{"hello\n"};
        constexpr auto    retries{10};
        for(auto i{0}; i < retries; ++i) {
            std::cout << "Try: " << i << "\n";
            try {
                co_await sock.async_write_some(buffer(message), use_awaitable);
            } catch(const boost::system::system_error& e) {
                std::cout << "Write exception: " << e.code() << '\n';
            }
        }
    }};

    auto future = co_spawn(pool.get_executor(), writeFunc(acceptedSock), use_future);

    ASSERT_EQ(future.wait_for(testTimeout), std::future_status::ready);
}

What I expect is that this test should write "Try: [number_of_retry]" 10 times (and also "Write exception: system:32" most of the times).

What it actually happens is that, after a few retries, the test hangs on a co_await sock.async_write_some call until timeout.

All relevant compiler information

I am using x86_64 GCC 13.3 on Ubuntu 24.04.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions