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:
- What do I need to do to get this event?
- 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.
-
You should not use
EPOLLONESHOTunless 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 withEPOLL_CTL_MOD. -
You should not use
EPOLLHUPto determine if a connection was closed. TheEPOLLHUPevent may be raised before all data is read from the socket input stream, even if the client diconnects gracefully. I recommend you to only useEPOLLIN. If there is no input left (because of forceful or graceful disconnect) thereadwould return0(end of file) and you can close the socket. -
Your
readcall will block the reading thread and consume the whole stream until End of file (connection closed). The whole point in usingepollis to not have to use awhile ( read(...) > 0 )loop. -
You should not use
EPOLLETbecause "the code runs multithreaded" but because you need it. You can write multithreaded code without the edge-triggered mode. The use ofEPOLLETrequires a throughout knowledge of the differences between blocking and non-blocking io. You can easily run into pitfalls (as mentioned in the manual) like edge-triggered starvation.