c++windowssocketswinsock2stdthread

recv doesn't work in a thread - Windows c++


I'm currently developing a TCP server and I use multi threading, so for this I init a server using a Server.start() which give me a fd like and then I init an infinite loop to accept and start new thread like this:

int main()
{
    spdlog::set_pattern("[%H:%M:%S %z] [%^---%L---%$] [thread %t] %v");

    Server server(9001);
    int sockfd = server.start();

    if (sockfd < 0)
    {
        spdlog::error("Cannot init server");
        return 1;
    }

    while (true)
    {
        int fd = server.loop();
        std::thread t(newclient, fd);
    }
}

void newclient(int fd)
{
    Handler handler;
    handler.loop(fd);
    closesocket(fd);
};

handler.loop:

void Handler::loop(int fd){
    std::string buffer;

    Communication communication(fd);

    while(true){
        buffer.erase();
        buffer = communication.recv_str();
        if (buffer == "") {
            continue;
        }
    }
    ...
}

and communication.recv_str():

std::string Communication::recv_str(){
    std::vector<char> buffer(CHUNK_SIZE);
    std::string rcv;
    long bytes_received = 0; 

    do {
        bytes_received = recv(fd, &buffer[0], CHUNK_SIZE, 0);

        if ( bytes_received < 0 ) {
            std::cout << "recv failed, err: " << WSAGetLastError() << std::endl;
        } else if ( bytes_received == 0 ) {
            return "";
        } else {
            rcv.append(buffer.cbegin(), buffer.cend());
        }
    } while( bytes_received == CHUNK_SIZE );

    return rcv;
}

so if I compile and run this when I try to connect to the server I got this message: crash message

But for a reason which I cannot explain it's crashing at the recv, I've tried to debug it but I cannot explain this thing. No message errors or others indications, I do not understand.

PS: sending works perfectly.


Solution

  • If a std::thread object is destructed and the associated thread is still running, std::terminate is called.

    This is specified in the documentation:

    If *this has an associated thread (joinable() == true), std::terminate() is called.

    In this part of your code:

    while (true)
    {
        int fd = server.loop();
        std::thread t(newclient, fd);
    }
    

    t's scope is ending at the end of the current iteration and the std::thread object is destroyed while it is most likely still running. Therefore std::terminate is called and the program exits.

    To solve the problem, you should keep all your std::thread objects as long as their associated thread is running. You could, for example, store them in a container in your Server class.