POLLNVAL
signifie que la valeur du descripteur de fichier n'est pas valide. Cela indique généralement une erreur dans votre programme, mais vous pouvez vous fier à poll
retour POLLNVAL
si vous avez fermé un descripteur de fichier et que vous n'avez ouvert aucun fichier depuis lors, cela pourrait avoir réutilisé le descripteur.
POLLERR
est similaire aux événements d'erreur de select
. Il indique qu'un read
ou write
call renverrait une condition d'erreur (par exemple, une erreur d'E/S). Cela n'inclut pas les données hors bande qui select
signaux via son errorfds
masque mais poll
signaux via POLLPRI
.
POLLHUP
signifie essentiellement que ce qui se trouve à l'autre extrémité de la connexion a fermé son extrémité de la connexion. POSIX le décrit comme
L'appareil a été déconnecté. Cet événement et POLLOUT sont mutuellement exclusifs ; un flux ne peut jamais être accessible en écriture si un raccrochage s'est produit.
C'est assez clair pour un terminal :le terminal est parti (même événement qui génère un SIGHUP :la session modem s'est terminée, la fenêtre de l'émulateur de terminal s'est fermée, etc.). POLLHUP
n'est jamais envoyé pour un dossier régulier. Pour les tuyaux et les prises, cela dépend du système d'exploitation. Linux définit POLLHUP
lorsque le programme à la fin de l'écriture d'un tube ferme le tube et définit POLLIN|POLLHUP
lorsque l'autre extrémité d'un socket a fermé le socket, mais POLLIN
uniquement pour un arrêt de socket. Ensemble *BSD récent POLLIN|POLLUP
lorsque la fin d'écriture d'un tube ferme le tube, et le comportement des sockets est plus variable.
Un POLLHUP
signifie que la prise n'est plus connectée. Dans TCP, cela signifie que FIN a été reçu et envoyé.
Un POLLERR
signifie que le socket a reçu une erreur asynchrone. Dans TCP, cela signifie généralement qu'un RST a été reçu ou envoyé. Si le descripteur de fichier n'est pas un socket, POLLERR
peut signifier que l'appareil ne prend pas en charge l'interrogation.
Pour les deux conditions ci-dessus, le descripteur de fichier de socket est toujours ouvert et n'a pas encore été fermé (mais shutdown()
peut-être déjà été appelé). Un close()
sur le descripteur de fichier libérera les ressources qui sont encore réservées au nom du socket. En théorie, il devrait être possible de réutiliser le socket immédiatement (par exemple, avec un autre connect()
appel).
Un POLLNVAL
signifie que le descripteur de fichier socket n'est pas ouvert. Ce serait une erreur de close()
il.
Cela dépend de la nature exacte de l'erreur. Utilisez getsockopt() pour voir le problème :
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Valeurs :http://www.xinotes.net/notes/note/1793/
Le plus simple est de supposer que le socket n'est plus utilisable dans tous les cas et de le fermer.
Exemple FIFO minimal
Une fois que vous comprenez quand ces conditions se produisent, il devrait être facile de savoir quoi en faire.
sondage.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 en amont.
Compiler avec :
gcc -o poll.out -std=c99 poll.c
Utilisation :
sudo mknod -m 666 poll0.tmp p
./poll.out
Sur un autre shell :
printf a >poll0.tmp
SONDAGE
Si vous ne modifiez pas la source :./poll.out
sorties :
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Donc :
POLLIN
se produit lorsque l'entrée devient disponiblePOLLHUP
se produit lorsque le fichier est fermé par leprintf
close(pfd.fd);
etpfd.fd *= -1;
nettoyer les choses, et nous arrêtons de recevoirPOLLHUP
poll
pend pour toujours
C'est le fonctionnement normal.
Vous pouvez maintenant renvoyer le FIFO pour attendre le prochain open
, ou quittez la boucle si vous avez terminé.
SONDAGE
Si vous commentez pfd.fd *= -1;
:./poll.out
imprime :
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
et boucle pour toujours.
Donc :
POLLIN
etPOLLHUP
etclose
s'est passé comme avant- puisque nous n'avons pas défini
pfd.fd
à un nombre négatif,poll
continue d'essayer d'utiliser lefd
que nous avons fermé - cela renvoie toujours
POLLNVAL
pour toujours
Nous voyons donc que cela n'aurait pas dû se produire et indique un bogue dans votre code.
POLLERR
Je ne sais pas comment générer un POLLERR
avec les FIFO. Faites-moi savoir s'il y a moyen. Mais cela devrait être possible avec file_operations
d'un pilote de périphérique.
Testé dans Ubuntu 14.04.