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:
POLLIN
ocurre cuando la entrada está disponiblePOLLHUP
sucede cuando el archivo es cerrado por elprintf
close(pfd.fd);
ypfd.fd *= -1;
limpia las cosas y dejaremos de recibirPOLLHUP
poll
cuelga 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:
POLLIN
yPOLLHUP
yclose
sucedió como antes- ya que no configuramos
pfd.fd
a un número negativo,poll
sigue intentando usar elfd
que cerramos - esto sigue devolviendo
POLLNVAL
por 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.