How to handle the Linux socket revents POLLERR, POLLHUP and POLLNVAL?
A POLLHUP
means the socket is no longer connected. In TCP, this means FIN has been received and sent.
A POLLERR
means the socket got an asynchronous error. In TCP, this typically means a RST has been received or sent. If the file descriptor is not a socket, POLLERR
might mean the device does not support polling.
For both of the conditions above, the socket file descriptor is still open, and has not yet been closed (but shutdown()
may have already been called). A close()
on the file descriptor will release resources that are still being reserved on behalf of the socket. In theory, it should be possible to reuse the socket immediately (e.g., with another connect()
call).
A POLLNVAL
means the socket file descriptor is not open. It would be an error to close()
it.
It depend on the exact error nature. Use getsockopt() to see the problem:
int error = 0;socklen_t errlen = sizeof(error);getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Values: http://www.xinotes.net/notes/note/1793/
The easiest way is to assume that the socket is no longer usable in any case and close it.
POLLNVAL
means that the file descriptor value is invalid. It usually indicates an error in your program, but you can rely on poll
returning POLLNVAL
if you've closed a file descriptor and you haven't opened any file since then that might have reused the descriptor.
POLLERR
is similar to error events from select
. It indicates that a read
or write
call would return an error condition (e.g. I/O error). This does not include out-of-band data which select
signals via its errorfds
mask but poll
signals via POLLPRI
.
POLLHUP
basically means that what's at the other end of the connection has closed its end of the connection. POSIX describes it as
The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.
This is clear enough for a terminal: the terminal has gone away (same event that generates a SIGHUP: the modem session has been terminated, the terminal emulator window has been closed, etc.). POLLHUP
is never sent for a regular file. For pipes and sockets, it depends on the operating system. Linux sets POLLHUP
when the program on the writing end of a pipe closes the pipe, and sets POLLIN|POLLHUP
when the other end of a socket closed the socket, but POLLIN
only for a socket shutdown. Recent *BSD set POLLIN|POLLUP
when the writing end of a pipe closes the pipe, and the behavior for sockets is more variable.