All below is from man epoll
page:
The function do_use_fd() uses the new ready file descriptor until EAGAIN is returned by either read(2) or write(2).
Code example for ET triggered :
for(;;) {
nfds = epoll_wait(kdpfd, events, maxevents, -1);
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) {
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client);
ev.events = EPOLLIN | EPOLLET;
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
fprintf(stderr, "epoll set insertion error: fd=%d\n",
client);
return -1;
}
}
else
do_use_fd(events[n].data.fd);
}
}
So for read/write
operation,we should do it by looping until a EAGAIN
is received;but why it's not the case for accept
?
IMO the above code will miss some requests when there're multiple client sockets waiting to be accepted, as it accepts only 1 client socket, we should also wrap it in a loop until EAGAIN
received.
Or maybe is there something I'm missing?
Look at how the listener socket is added to the epollfd
:
ev.events = EPOLLIN; // this is the crucial bit
ev.data.fd = listen_sock;
It's not added in edge-triggered, it's added in level-triggered. So no need for a loop until EAGAIN
on that one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With