Forum Programmation.c Problème avec select et pipe

Posté par .
Tags : aucun
1
10
mar.
2010
Bonjour à tous,

Pour un de mes projets, j’ai eu à faire communiquer deux programmes à l’aide d’un pipe. Rien de bien sorcier. Puis, j’ai eu besoin de gérer le timeout. J’ai tenté de le faire avec select (toujours rien de magique), et à ma grande surprise… ça ne fonctionne pas !

Voici mon code, simplifié le plus possible. C’est une utilisation basique de select(), et je ne vois pas comment j’ai pu me planter là dedans. Si quelqu’un arrive à trouver, il me permettra d’assouvir ma curiosité et donc de dormir cette nuit ;)


#include
#include
#include
#include
#include

static int rd_fd, wr_fd;

void phy_send_byte(uint8_t b)
{
if(write(wr_fd, &b, 1) < 0) {
perror("phy_send_byte");
exit(1);
}
}

uint8_t phy_recv_byte(int timeout, int *timed_out)
{
uint8_t b;
fd_set wait_fds;
struct timeval sel_timeout = {.tv_sec = timeout, .tv_usec = 0};

FD_ZERO(&wait_fds);
FD_SET(rd_fd, &wait_fds);

if(select(1, &wait_fds, NULL, NULL, &sel_timeout) == 0) {
if(timed_out != NULL)
*timed_out = 1;
return b;
}

if(read(rd_fd, &b, 1) < 0) {
perror("phy_recv_byte");
exit(1);
}

if(timed_out)
*timed_out = 0;

return b;
}

int main(int argc, char **argv)
{
int server_pipe[2];
int timed_out;

pipe(server_pipe);

if(fork() == 0) {
rd_fd = server_pipe[0];
fprintf(stderr, ">>> %x\n", phy_recv_byte(5, &timed_out));
}
else {
wr_fd = server_pipe[1];
phy_send_byte(42);
fprintf(stderr, "<<< %x\n", 42);
wait(NULL);
}
return 0;
}


Si vous lancez le programme, vous remarquerez que le select() finit en timeout, comme si aucune donnée n’était reçue. Mais si vous commentez le select(), le read() renvoie les données !

Plus étrange encore, si je remplace le select() par poll(), ça fonctionne comme un charme.


struct pollfd pfd;

if(timeout <= 0)
timeout = -1;
pfd.fd = rd_fd;
pfd.events = POLLIN;
if(poll(&pfd, 1, timeout) == 0) {
if(timed_out != NULL)
*timed_out = 1;
return b;
}


Je ne cherche pas tant la solution qu’une explication… Merci à tous ceux qui feront avancer l’enquête !
  • # Damned !

    Posté par . Évalué à 1.

    Encore pawned par templeet. Les includes sont les suivants :

    stdint.h
    stdlib.h
    stdio.h
    sys/wait.h
    sys/select.h
  • # Premier paramètre de select

    Posté par (page perso) . Évalué à 7.

    Bonjour,

    Le premier paramètre de select doit être le numéro du plus grand descripteur dans un des ensembles passés plus 1:

    if(select(rd_fd + 1, &wait_fds, ...
    • [^] # Re: Premier paramètre de select

      Posté par . Évalué à 1.

      Ah, c’était ça, merci :)

      (j’avais interprété « The first nfds descriptors shall be checked in each set » comme les n premiers descripteurs de l’ensemble passé en paramètre, pas de l’ensemble des descripteurs ouverts)
  • # re

    Posté par (page perso) . Évalué à 2.

    • [^] # Re: re

      Posté par . Évalué à 1.

      Je n’ai que deux processus qui communiquent entre eux… un socket pour ça, c’est un peu overkill ;)

      Mais merci quand même
      • [^] # Re: re

        Posté par (page perso) . Évalué à 1.

        Regarde la partie multplexage E/S qui fais un select entre les fd, le socket n'est qu'un fd, tu met ce que tu veux ;)
        • [^] # Re: re

          Posté par (page perso) . Évalué à 1.

          Section: '5 Declaration des entrees a surveiller dans notre boucle for.'

          Client ou serveur c'est la meme chose pour cette partie.

          Apres je me plante peut etre mais je pense que c'est ca que tu cherche.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.