2010-11-16 37 views
2

Les man pages for select() ne répertorient pas EAGAIN comme code d'erreur possible pour la fonction select().select() sur un tuyau en mode de blocage renvoie EAGAIN

Quelqu'un peut-il expliquer dans quels cas select() peut produire une erreur EAGAIN? Si je comprends bien select_tut man page, EAGAIN peut être produit en envoyant un signal au processus qui est bloqué en attente de sélection(). Est-ce correct?

Depuis que je suis en utilisant select() en mode blocage avec délai d'attente, comme ceci:

bool selectRepeat = true; 
int res = 0; 
timeval selectTimeout(timeout); 
while (true == selectRepeat) 
{ 
    res = ::select(fd.Get() + 1, 
        NULL, 
        &writeFdSet, 
        NULL, 
        &selectTimeout); 
    selectRepeat = ((-1 == res) && (EINTR == errno)); 
} 

dois-je répéter la boucle lorsque le numéro d'erreur est EAGAIN?

+0

Montrez-nous le code qui configure 'writeFdSet'. J'imagine que c'est faux. Aussi, êtes-vous sûr que la valeur de retour est -1? Sinon, 'errno' n'a rien à voir avec' select' et a probablement été défini par un appel précédent. –

+0

@R Les pages man de select_tut m'ont confondu, car il mentionne EAGAIN et sélectionne. Le retour de select est 0, et EAGAIN est défini qui sait où. –

Répondre

4

select() ne retournera pas EAGAIN en aucune circonstance. Il peut cependant renvoyer EINTR s'il est interrompu par un signal (Ceci s'applique à la plupart des appels système).

EAGAIN (ou EWOULDBLOCK) peuvent être renvoyés de read, write, recv, send, etc.

+0

http://linux.die.net/man/2/select_tut Aller à ce lien, et faites défiler jusqu'à "Select laws", où il est dit que select() peut retourner EAGAIN. J'ai également été intrigué pour obtenir EAGAIN de select(), d'où la question. –

+2

@VJo: C'est juste une ambiguïté dans le tutoriel, cela n'a aucun sens que 'select' renvoie EWOULDBLOCK' /' EAGAIN'. – Hasturkun

1

EAGAIN est techniquement pas une erreur, mais une indication que l'opération terminée sans terminer, et vous devriez ... euh ... essayez encore. Vous voudrez probablement écrire la logique pour réessayer, mais pas infiniment. Si c'était sûr, ils l'auraient fait eux-mêmes dans l'API.

Si vous pensez que conserver un code d'erreur non-erreur idiot comme cela est un peu mauvaise conception de l'interface client, vous n'êtes pas le premier. Il s'avère que EAGAIN comme un code d'erreur a un long historique intéressant dans Unix. Entre autres choses, il a engendré l'essai largement diffusé sur la conception de logiciels The Rise of Worse-is-Better. Il y a quelques paragraphes au milieu qui expliquent pourquoi Unix doit retourner cela parfois. Oui, il a en effet quelque chose à voir avec la réception d'interruptions pendant une E/S. Ils appellent cela le PC perdant.

Beaucoup créditent cet essai comme l'une des inspirations pour la programmation Agile.

+0

AFAIK, Dans le contexte des opérations socket/fichier, 'EAGAIN' signifie toujours que l'opération ne peut pas être complétée sans blocage, alors que la fd a été configurée comme non bloquante. Un logiciel bien comporté ne boucle pas l'appel qui a 'EAGAIN' mais plutôt' select'/'poll' pour l'état de préparation, ou ne définit pas le fd non-bloquant en premier lieu. seulement 'EINTR' est retourné lorsqu'il est interrompu par un signal. – Hasturkun

+0

@Hasturkun - Cela ressemble plus à 'EWOULDBLOCK' –

+2

' EAGAIN' n'est pas un comportement valide pour 'select'. Voir http://www.opengroup.org/onlinepubs/9699919799/functions/select.html et notez "Si aucun des descripteurs sélectionnés n'est prêt pour l'opération demandée, la fonction pselect() ou select() bloquera jusqu'à au moins l'une des opérations demandées devient prête, jusqu'à ce que le délai expire, ou jusqu'à ce qu'elle soit interrompue par un signal. " –