POLLNVAL significa que el valor del descriptor de archivo no es válido. Por lo general, indica un error en su programa, pero puede confiar en poll devolviendo POLLNVAL si ha cerrado un descriptor de archivo y no ha abierto ningún archivo desde entonces, es posible que haya reutilizado el descriptor.
POLLERR es similar a los eventos de error de select . Indica que un read o write call devolvería una condición de error (por ejemplo, error de E/S). Esto no incluye datos fuera de banda que select señales a través de su errorfds máscara pero poll señales a través de POLLPRI .
POLLHUP básicamente significa que lo que está en el otro extremo de la conexión ha cerrado su extremo de la conexión. POSIX lo describe como
El dispositivo ha sido desconectado. Este evento y POLLOUT son mutuamente excluyentes; nunca se puede escribir en una transmisión si se ha producido un bloqueo.
Esto es bastante claro para una terminal:la terminal se ha ido (mismo evento que genera un SIGHUP:la sesión del módem se ha terminado, la ventana del emulador de terminal se ha cerrado, etc.). POLLHUP nunca se envía para un archivo regular. Para tuberías y enchufes, depende del sistema operativo. Linux establece POLLHUP cuando el programa en el extremo de escritura de una tubería cierra la tubería y establece POLLIN|POLLHUP cuando el otro extremo de un zócalo cerró el zócalo, pero POLLIN sólo para un apagado de socket. Conjunto reciente de *BSD POLLIN|POLLUP cuando el extremo de escritura de una tubería cierra la tubería, y el comportamiento de los enchufes es más variable.
Un POLLHUP significa que el enchufe ya no está conectado. En TCP, esto significa que se ha recibido y enviado FIN.
Un POLLERR significa que el socket recibió un error asíncrono. En TCP, esto normalmente significa que se ha recibido o enviado un RST. Si el descriptor de archivo no es un socket, POLLERR podría significar que el dispositivo no es compatible con el sondeo.
Para las dos condiciones anteriores, el descriptor del archivo de socket aún está abierto y aún no se ha cerrado (pero shutdown() puede que ya hayan sido llamados). Un close() en el descriptor de archivo liberará los recursos que todavía están reservados en nombre del socket. En teoría, debería ser posible reutilizar el socket inmediatamente (por ejemplo, con otro connect() llamar).
Un POLLNVAL significa que el descriptor del archivo de socket no está abierto. Sería un error close() eso.
Depende de la naturaleza exacta del error. Use getsockopt() para ver el problema:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Valores:http://www.xinotes.net/notes/note/1793/
La forma más fácil es asumir que el socket ya no se puede utilizar en ningún caso y cerrarlo.
Ejemplo FIFO mínimo
Una vez que comprenda cuándo ocurren esas condiciones, debería ser fácil saber qué hacer con ellas.
encuesta.c
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
GitHub ascendente.
Compilar con:
gcc -o poll.out -std=c99 poll.c
Uso:
sudo mknod -m 666 poll0.tmp p
./poll.out
En otro caparazón:
printf a >poll0.tmp
POLLHUP
Si no modifica la fuente:./poll.out salidas:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Entonces:
POLLINocurre cuando la entrada está disponiblePOLLHUPsucede cuando el archivo es cerrado por elprintfclose(pfd.fd);ypfd.fd *= -1;limpia las cosas y dejaremos de recibirPOLLHUPpollcuelga para siempre
Esta es la operación normal.
Ahora puede volver a configurar el FIFO para esperar el próximo open , o salga del bucle si ha terminado.
POLLNAL
Si comentas pfd.fd *= -1; :./poll.out imprime:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
y bucles para siempre.
Entonces:
POLLINyPOLLHUPyclosesucedió como antes- ya que no configuramos
pfd.fda un número negativo,pollsigue intentando usar elfdque cerramos - esto sigue devolviendo
POLLNVALpor siempre
Entonces vemos que esto no debería haber sucedido e indica un error en su código.
POLLERR
No sé cómo generar un POLLERR con FIFO. Déjame saber si hay manera. Pero debería ser posible con file_operations de un controlador de dispositivo.
Probado en Ubuntu 14.04.