How to get errno when epoll_wait returns EPOLLERR?
Use getsockopt and SO_ERROR to get the pending error on the socket
int error = 0;
socklen_t errlen = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen) == 0)
{
printf("error = %s\n", strerror(error));
}
meaning of EPOLLERR from epoll_wait with a pipe
Other than the other end being closed, there aren't any errors on a write end of a pipe which could be detected by epoll. The few errors that are possible on an actual call to write() could not be known in advance (e.g., if you pass an invalid buffer pointer), so epoll cannot detect them. Therefore, if epoll tells you there's an error, it is EPIPE.
(OK, there is actually another possible error condition, but it can be triggered only by a programming error: if you close the file descriptor and then use epoll_wait while it is on the list - I don't know how epoll will react to that).
c++ socket accept() get Resource deadlock avoided errno with epoll
Error code 11 is EAGAIN
, which is a very common error code to encounter when dealing with non-blocking socket I/O. It means the requested operation has nothing to do, try it again later.
In the case of accept()
, it means:
EAGAIN
orEWOULDBLOCK
The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 and POSIX.1-2008 allow either error to be returned for this case, and do not require these constants to have the same value, so a portable application should check for both possibilities.
This means you are calling accept()
at the wrong time, when the listening socket does not have any clients to accept. Double check your epoll()
usage, it likely has a logic bug in it that is causing you to call accept()
prematurely.
For instance, after accept()
has successfully accepted a client, you are assigning the listening socket instead of the client socket to event.data.fd
when calling epoll_ctl(EPOLL_CTL_ADD)
:
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = serverFd; // <-- HERE, SHOULD BE acceptFd INSTEAD!
int ctlClientResult = epoll_ctl(epollFd, EPOLL_CTL_ADD, acceptFd, &event);
As such, when the client has data waiting to be read, your loop will end up calling accept()
on the listening socket instead of calling recv()
on the client socket.
Also, you are not checking the reported event.events
field for socket errors. If an error occurs on a client socket, the reported events
may include the EPOLLERR
and/or EPOLLHUP
flags. You should check for those flags and if present then close the client socket, before checking for the EPOLLIN
flag to call recv()
.
Also, note that in your example, it is not necessary to call epoll_ctl(EPOLL_CTL_DEL)
before calling close()
on a socket. Closing a socket file descriptor will automatically remove it from the epoll instance that is monitoring it.
epoll_wait fails due to EINTR, how to remedy this?
Certain signal handler will interrupt epoll_wait()
, select()
and similar system calls on any Unix or Linux. This is by design so you can interrupt these system calls.
You cannot directly remedy it. The typical solution is to explicitly check the errno for EINTR and to execute epoll_wait()
again:
int nr;
do {
nr = epoll_wait(epfd, events, maxevents, timeout);
} while (nr < 0 && errno == EINTR);
Also see: gdb error: Unable to execute epoll_wait: (4) Interrupted system call
EBADF while recv after epoll_wait
When the remote host closes the socket, epoll()
reports both a HUP
and an EPOLLIN
for the file descriptor.
You check for EPOLLRDHUP
first, and close the socket; then you check for EPOLLIN
, find that too, and try to call recv()
. Since the socket has been closed, the file descriptor is no longer valid, and you get EBADF
(the closed socket is removed from the epoll
set, so subsequent epoll_wait()
calls won't return it; but for the epoll_wait()
that has already returned it's too late - the EPOLLIN
is already waiting in your events[i]
.
You need to stop checking for events after you call disconnectDriver()
(if it closed the file descriptor):
if (events[i].events & EPOLLRDHUP) {
std::cout << "EPOLLRDHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
continue;
}
Related Topics
Apache Cgi in User Directory "End of Script Output Before Headers"
Bash Script Does Not Continue to Read The Next Line of File
How to Add Export Statement in a Bash_Profile File
Why I Am Not Getting Signal Sigkill on Kill -9 Command in Bash
Tools Required to Learn Arm on Linux X86 Platform
Linux of Equivalent Cryptprotectmemory
Ssh Connection to Azure Vm with Terraform
Short Command to Find Total Size of Files Matching a Wild Card
Extract Lines When Column K Is Empty with Awk/Perl
Only Accept Http Connections from Localhost in Go
Executing Exe or Bat File on Remote Windows Machine from *Nix
How to Redirect Http to Https Using Gcp Load Balancer
Cannot Change The Maximum Open Files Per Process with Sysctl
Are System Calls on Windows Inherently Slower Than Linux
How Does Linux Support More Than 512Gb of Virtual Address Range in X86-64