Home > Enterprise >  asio (standalone, non-boost) async_write handler not called by io_context.run() or io_context.poll()
asio (standalone, non-boost) async_write handler not called by io_context.run() or io_context.poll()

Time:11-05

(I know the tag is boost-asio, but I'm using standalone asio) I am debugging my tcp client application, and it boils down to this:

// checkpoint 1
asio::async_write(socket, asio::buffer(input), [](const asio::error_code &ec, std::size_t bytes_transferred) {
    // checkpoint 2
}
// checkpoint 3
io_context.run()
// checkpoint 4

So pretty much checkpoint 1, 3, 4 get called (i just std::cout something to console), but checkpoint 2 does not. The actual write operation DOES WORK though, because my backend server receives the write. The application is completely single-threaded, the io_context and socket are valid, socket.is_open() returns true. I would appreciate more clues as to how I can debug this, as I don't have much experience with asio.

EDIT: this is a not so boiled down version:
(print() is a template function that std::cout's everything)
network.h:

class Network
{
public:
    Network();
    void ConnectToServer();
    void Update();
    void Test(std::string input);

private:
    asio::io_context io_context;
    asio::ip::tcp::socket socket;
    asio::ip::basic_resolver_results<asio::ip::tcp> endpoints;
}  

network.cpp:

Network::Network() : socket(io_context)
{
    asio::ip::tcp::resolver resolver(io_context);
    endpoints = resolver.resolve(serverIP, serverPort); // ip and port are defined static variables
}
void Network::ConnectToServer()
{
    asio::connect(socket, endpoints);

    std::string initMessage = "I just connected";
    asio::write(socket, asio::buffer(initMessage));

    asio::streambuf receiveBuffer;
    asio::read_until(socket, receiveBuffer, "\n");
    std::istream responseStream(&receiveBuffer);

    std::string response;
    std::getline(responseStream, response);
    print("server response: "   response);
}
void Network::Update()
{
    print("about to poll");
    io_context.poll();
    print("just polled");
}
void Network::Test(std::string input)
{
    print("about to async_write");
    asio::async_write(socket, asio::buffer(input), [](const asio::error_code &ec, std::size_t bytes_transferred)
                      { 
                        try{
                            print("async_write completed no error");
                        }
                        catch(const std::exception& e)
                        {
                            print("async_write ERROR");
                        } });
    print("after async_write call");
}

main.cpp:

Network *network;

int main(void)
{
    // other single-threaded stuff
    network = new Network();
    network->ConnectToServer();
    network->Test("hello");
    // other single-threaded stuff
    print("main loop starting");
    while(true) // !glfwWindowShouldClose(window) - it's a glfw aplication
    {
        // other single-threaded stuff
        network->Update();
        if(some player input)
        {
            print("player input");
            network->Test("in main loop");
        }
        // other single-threaded stuff
    }
}

and this is what I get:

about to connect to server
connected to server
server response: You connected successfully
about to async_write
after async_write call
main loop starting
about to poll
async_write completed no error
just polled
about to poll
just polled
about to poll
just polled
|
|
about to poll
just polled
player input
about to async_write
after async_write call
about to poll
just polled
about to poll
just polled
|
|

My server receives a correct write from both calls to Test() - the one before the main loop and the one inside the main loop, but the completion handlers for those asyncs don't get called by the poll(). (note: Network *network is in global scope because i use it as an extern from other cpp files). And I don't make any other calls to network's functions.

CodePudding user response:

Please include the self-contained code. The code shown is obviously ok, and there will be another difference that you're not showing here.

Start from e.g. this enter image description here

What could be happening potentially is that you start run() before the async operation(s) and the services runs out of work before the completion ever gets registered. Obviously, that is not the case in your question code.

UPDATE TO EDITS

The most glaring problem is using async_write with a stack buffer. That invokes enter image description here

  • Related