Checking man epoll(7) I see a mysterious line: setnonblocking(conn_sock);
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Code to set up listening socket, 'listen_sock',
(socket(), bind(), listen()) omitted. */
epollfd = epoll_create1(0);
if (epollfd == -1) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
exit(EXIT_FAILURE);
}
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_wait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &addr, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
AFAIK epoll_wait
already causes function accept
to be non-blocking, or rather, it allows the detection of ready-to-use fds, so the server can already serve concurrently all connected clients. I don't understand this manipulation of the file descriptor, what is this function supposed to do?
AFAIK epoll already causes function accept to be non-blocking
And as far as I know, that is not correct. I don't see anything in the man page documentation for epoll_ctl or epoll(7) that would suggest that. There's plenty of references in epoll(7) that suggest using non-blocking file descriptors.
Regardless, I'm guessing setnonblocking
is just a function that does this:
int setnonblocking(sock)
{
int result;
int flags;
flags = ::fcntl(_sock, F_GETFL, 0);
if (flags == -1)
{
return -1; // error
}
flags |= O_NONBLOCK;
result = fcntl(_sock , F_SETFL , flags);
return result;
}
I just a similar version of that above function in my own code that uses epoll for TCP sockets. I apply the above function on both the listen socket that is passed to accept
as well as the connection sockets returned from accept
.