zeromq / cppzmq

Header-only C++ binding for libzmq
http://www.zeromq.org
MIT License
1.9k stars 757 forks source link

Dealer socket, memory leak issue: The file descriptor doesn't get delete it. Too many open files descriptor #639

Open SeifHadrich opened 2 months ago

SeifHadrich commented 2 months ago

In a dealer socket if there is no response received, then the file descriptor will stay alive. This will cause the application to consume all the available file descriptors and then zmq fails with this error : terminate called after throwing an instance of 'zmq::error_t' what(): Too many open files qemu: uncaught target signal 6 (Aborted) - core dumped Aborted The ZMQ_LINGER doesn't seem to have an affect in this type of socket

Here a simple code to create the issue :

#include <zmq.hpp>
#include <future>
#include <iostream>

zmq::context_t m_ctx;

void client_call()
{
    zmq::socket_t socket(m_ctx, zmq::socket_type::dealer);
    int timeout_ms = 100;
    socket.set(zmq::sockopt::rcvtimeo, timeout_ms);
    socket.set(zmq::sockopt::sndhwm, timeout_ms);
    socket.set(zmq::sockopt::linger, timeout_ms);
    socket.set(zmq::sockopt::conflate, 1);
    socket.connect("inproc://test");

    if (socket) {
        // Wait for response or timeout event
        zmq::pollitem_t items[] = {{socket, 0, ZMQ_POLLIN, 0}};
        zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout_ms));
        // The server responds within the timeout period
        if ((items[0].revents & ZMQ_POLLIN)) {
            zmq::message_t msg;
            auto rxres = socket.recv(msg);
            if (rxres && (rxres.value() > 0))

            {
                std::cout << "Server response : " << msg << std::endl;
            }
        }
        // The request times out, so drop it and close the socket
        else {
            socket.close();
            // ! Memory leak issue :The file descriptor doesn't get deleted or freed
            std::cout << " Server is not responding" << std::endl;
        }
    }
}

int main()
{
    int i = 0;
    while (1) {
        i++;
        std::cout << "Client call number " << i << std::endl;
        client_call();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}