Comment faire en sorte que toutes les sorties sur un tube avec asynchrone IO soient terminées avant la fermeture

J’utilise un tube pour lire la sortie d’une fonction en lui passant un descripteur de fichier. Pour lire la sortie de manière asynchrone, je configure l’extrémité “read” du canal en mode ASYNC NON BLOCKING et je configure un gestionnaire IO en utilisant SIGACTION. Mon code ressemble à ceci:

struct sigaction io_act; struct sigaction io_act_old; sigset_t block_mask; /* create the pipe */ pipe (pipe_fd); /* set the reading end of pipe in ASYNC mode */ fcntl (pipe_fd[0], F_SETOWN, getpid()); fcntl (pipe_fd[0], F_SETFL, O_ASYNC | O_NONBLOCK); /* add an I/O handler for SIGIO */ sigemptyset (&block_mask); io_act.sa_handler = sigio_handler; io_act.sa_mask = block_mask; io_act.sa_flags = SA_RESTART; sigaction (SIGIO, &io_act, &io_act_old); /* executing the function that generate output in given FILEDES */ my_generate_output (pipe_fd[1]); close(pipe_fd[1]); /* this sleep should not be needed (subject of question) */ sleep(1); close (pipe_fd[0]); /* restore previous signal handler */ sigaction (SIGIO, &io_act_old, NULL); 

Le problème est que si je omet l’appel de fonction de veille, je peux fermer le canal et désactiver le gestionnaire SIGIO avant la fin de la sortie. La conséquence est que l’application abandonne en raison d’un signal SIGIO non géré (message “E / S possibles”).

Comment puis-je m’assurer que toutes les sorties ont été lues depuis le canal avant de désactiver le gestionnaire SIGIO?

Pour obtenir le nombre d’octets lisibles, vous pouvez utiliser l’ ioctl FIONREAD , qui n’est pas très portable. Voir cette question comme un exemple artificiel.

Vous pouvez également tester la disponibilité des choses à lire avec le sondage , sélectionnez et amis.

Et la condition de fin de fichier est signalée avec read renvoyant 0 comme count.

ADDENDA

Selon read (2) syscall man page, read échoue avec errno ==:

  EAGAIN or EWOULDBLOCK The file descriptor fd refers to a socket and has been marked nonblocking (O_NONBLOCK), and the read would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. 

Je crois que vous ne pouvez pas savoir s’il y aura toujours plus de données dans la pipe. Donc, si vous contrôlez le processus qui écrit dans le canal, vous devrez écrire une séquence spéciale d’octets “END-OF-DATA” convenue pour que le lecteur sache quand arrêter.