POLLNVAL
significa che il valore del descrittore di file non è valido. Di solito indica un errore nel tuo programma, ma puoi fare affidamento su poll
restituendo POLLNVAL
se hai chiuso un descrittore di file e da allora non hai aperto alcun file, ciò potrebbe aver riutilizzato il descrittore.
POLLERR
è simile agli eventi di errore di select
. Indica che un read
o write
call restituirebbe una condizione di errore (ad es. errore di I/O). Questo non include i dati fuori banda quali select
segnali tramite il suo errorfds
mask ma poll
segnali tramite POLLPRI
.
POLLHUP
significa sostanzialmente che ciò che è all'altro capo della connessione ha chiuso la sua estremità della connessione. POSIX lo descrive come
Il dispositivo è stato disconnesso. Questo evento e POLLOUT si escludono a vicenda; uno stream non può mai essere scrivibile se si è verificato un blocco.
Questo è abbastanza chiaro per un terminale:il terminale è andato via (stesso evento che genera un SIGHUP:la sessione del modem è stata terminata, la finestra dell'emulatore di terminale è stata chiusa, ecc.). POLLHUP
non viene mai inviato per un file normale. Per tubi e prese, dipende dal sistema operativo. Linux imposta POLLHUP
quando il programma all'estremità di scrittura di una pipe chiude la pipe e imposta POLLIN|POLLHUP
quando l'altra estremità di un socket chiudeva il socket, ma POLLIN
solo per un arresto della presa. Set *BSD recente POLLIN|POLLUP
quando l'estremità di scrittura di una pipe chiude la pipe e il comportamento per i socket è più variabile.
Un POLLHUP
significa che la presa non è più collegata. In TCP, questo significa che FIN è stato ricevuto e inviato.
Un POLLERR
significa che il socket ha ricevuto un errore asincrono. In TCP, questo in genere significa che è stato ricevuto o inviato un RST. Se il descrittore di file non è un socket, POLLERR
potrebbe significare che il dispositivo non supporta il polling.
Per entrambe le condizioni di cui sopra, il descrittore di file socket è ancora aperto e non è stato ancora chiuso (ma shutdown()
potrebbe essere già stato chiamato). Un close()
sul descrittore di file rilascerà le risorse che sono ancora riservate per conto del socket. In teoria, dovrebbe essere possibile riutilizzare il socket immediatamente (ad esempio, con un altro connect()
chiamata).
Un POLLNVAL
significa che il descrittore del file socket non è aperto. Sarebbe un errore close()
esso.
Dipende dalla natura esatta dell'errore. Usa getsockopt() per vedere il problema:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Valori:http://www.xinotes.net/notes/note/1793/
Il modo più semplice è presumere che il socket non sia più utilizzabile in ogni caso e chiuderlo.
Esempio FIFO minimo
Una volta capito quando si verificano queste condizioni, dovrebbe essere facile sapere cosa farne.
sondaggio.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 a monte.
Compila con:
gcc -o poll.out -std=c99 poll.c
Utilizzo:
sudo mknod -m 666 poll0.tmp p
./poll.out
Su un'altra shell:
printf a >poll0.tmp
POLLHUP
Se non modifichi la fonte:./poll.out
uscite:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Quindi:
POLLIN
accade quando l'input diventa disponibilePOLLHUP
accade quando il file viene chiuso dalprintf
close(pfd.fd);
epfd.fd *= -1;
sistema le cose e smettiamo di riceverePOLLHUP
poll
si blocca per sempre
Questa è l'operazione normale.
Ora puoi rispondere al FIFO per attendere il prossimo open
o esci dal ciclo se hai finito.
POLLNALE
Se commenti pfd.fd *= -1;
:./poll.out
stampe:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
e si ripete all'infinito.
Quindi:
POLLIN
ePOLLHUP
eclose
successo come prima- poiché non abbiamo impostato
pfd.fd
a un numero negativo,poll
continua a provare a usare ilfd
che abbiamo chiuso - questo continua a restituire
POLLNVAL
per sempre
Quindi vediamo che questo non sarebbe dovuto accadere e indica un bug nel tuo codice.
POLLERR
Non so come generare un POLLERR
con FIFO. Fammi sapere se c'è modo. Ma dovrebbe essere possibile con file_operations
di un driver di dispositivo.
Testato in Ubuntu 14.04.