Search code examples
c++clinuxepoll

epoll does not signal an event when socket is close


I have a listener socket, every new connection I get I add it to epoll like this:

int connfd = accept(listenfd, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT | EPOLLHUP;
ev.data.fd = connfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev)

When new data is received, epoll signal 'EPOLLIN' event - as expected.

In such a situation I read all the information as follows:

long read = 0;
do {
    read = recv(events[n].data.fd, buffer, sizeof (buffer), 0);
} while (read > 0);

In case I disconnected brutally or normally, epoll does not signal an event.

This code run in each thread, that's what I'm using EPOLLET.

So my question:

  1. What do I need to do to get this event?
  2. What do I need to do to close the socket so that there is no leakage of resources?

Solution

  • There are a few problems with your attempt.

    1. You should not use EPOLLONESHOT unless you know what you are doing and you really need it. It disables the report of any other events to the epoll instance until you enable it again with EPOLL_CTL_MOD.

    2. You should not use EPOLLHUP to determine if a connection was closed. The EPOLLHUP event may be raised before all data is read from the socket input stream, even if the client disconnects gracefully. I recommend you to only use EPOLLIN. If there is no input left (because of forceful or graceful disconnect), the read() would return 0 (EOF) and you can close the socket.

    3. Your read() call will block the reading thread and consume the whole stream until EOF (connection closed). The whole point in using epoll() is to not have to use a while ( read(...) > 0 ) loop.

    4. You should not use EPOLLET because "the code runs multithreaded" but because you need it. You can write multithreaded code without the edge-triggered mode. The use of EPOLLET requires a thorough knowledge of the differences between blocking and non-blocking I/O. You can easily run into pitfalls (as mentioned in the manual), like edge-triggered starvation.