Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: [SOLVED] poll() ; vreemd gedrag of niet  (gelezen 984 keer)

Offline kuifje09

  • Lid
[SOLVED] poll() ; vreemd gedrag of niet
« Gepost op: 2013/06/04, 23:08:47 »
Hallo medeprogrammeurs. Ik probeer een programmaatje te maken dat leest van standaard input en van het keyboard.
Dat kan hetzelfde zijn maar zoals ik het gebruik niet.
Ik ben uitgegaan van enige voorbeelden van het web, maar daar lijkt iets niet mee te kloppen.
Allereerst, met select() ben ik aan het stoeten geweest, maar kreeg het niet goed aan het werk. Daarna overgestapt naar poll(), wat bijna hetzelfde doet maar net iets anders. Ook daar werkt het niet goed mee. In de voorbeelden word uitgegaan van het meegeven van een array aan filedescripters die in de gaten gehouden moeten worden, maar dat werkt al helemaal niet, althans , niet bij mij.
Ik test nu alle filedescriptors 1 voor 1, dat werkt al een stuk beter. Maar.  Als de input is opgedroogd of als het aanbiedende programma is gestopt, dan loopt de boel in het honderd. Ook al zit er nog wat in de buffer. Dan nog kan het met de vlag POLLINP niet gevangen worden. Dus een or met POLLHUP erbij, en hopla, we kunnen het wel vangen. Maar dat is dus niet goed.
Dann testen we dus ook maar op EOF, maar helaas. Er komt geen eind aan de echt wel lege input... Wat is hier aan de hand.

Graag een reactie.  In de source staat hoe je het eventueel kan testen/gebruiken als voorbeeld. De passwdfile is altijd een gewillig slachtoffer.

Dit is de source:



// cc -o noot noot.c -Wall

// run as i.e.  Passwdfile < 50 !  else fix 50 into some larger value....

// Run: cat /etc/passwd | while read line; do echo $line; done | ./noot


#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <poll.h>

int
main(void)
{
  struct pollfd fds0,fds1;
  int Myfd[2];
  //struct timespec tv;
  int retval,count;
  char s[64000];
  FILE *fIn;
  int fdI;
  if((fIn = fopen("/dev/tty","r")) != NULL ){
     fdI = fileno(fIn);
     printf("fdI == %d\r\n",fdI);
     sleep(1);
  } else {
     printf("Open /dev/tty failed.\r\n");
  };

  // No echo from tty
  system("/bin/stty -F/dev/tty -echo");

  printf("type something : ");
  fgets(s,sizeof(s)-1,fIn);
  printf("keyboard : %s\r\n",s);
  sleep(1);

//  printf("read something : ");
//  fgets(s,sizeof(s)-1,stdin);
//  printf("stdin : %s\r\n",s);
//  sleep(1);

   /* Watch stdin (fd 0) to see when it has input. */
    Myfd[0]=0;
    Myfd[1]=fdI;
    fds0.fd = Myfd[0];     // stdin
    fds0.events = POLLIN;
    fds1.fd = Myfd[1];     // Keyboard
    fds1.events = POLLIN;

  while(count < 50){

    /* Wait up to X seconds. */
    //tv.tv_sec = 1;
    //tv.tv_nsec = 5000000;

    retval = poll(&fds0, 1, 10);
    retval += poll(&fds1, 1, 10);
    /* Don't rely on the value of tv now if it was used! */

//    retval += poll(&fds2, 1, 100);
//    /* Don't rely on the value of tv now if it was used! */
//    printf("retval == %d\r\n",fds2.revents);

    count+=1;

    if (retval == -1) {
        //perror("poll()");
    } else {
      if (retval>0) {                 // Data is available now.
        if(fds0.revents & (POLLIN|POLLHUP)) {   // data from pipe ?
           printf("retval 0 == %d\r\n",fds0.revents);
           if(fgets(s,sizeof(s)-1,stdin) != EOF){
           printf("From 0 : %s",s);
           };
        };
        if(fds1.revents & POLLIN) {   // data from keyboard ?
           printf("retval 1 == %d\r\n",fds1.revents);
           fgets(s,sizeof(s)-1,fIn);
           printf("From 1 : %s",s);
        };
       } else {
        //printf("No data within X seconds.\n");
       };
    };
  };

  // Again, echo from tty
  system("/bin/stty -F/dev/tty echo");

  exit(EXIT_SUCCESS);
};
« Laatst bewerkt op: 2013/06/05, 13:02:39 door kuifje09 »

Offline kuifje09

  • Lid
Re: poll() ; vreemd gedrag of niet
« Reactie #1 Gepost op: 2013/06/04, 23:17:24 »
O ja... De while read na de cat was bedoeld om een sleep tussen te zetten. b.v.   echo $line; sleep 1; done.
Dat geeft een duidelijker beeld hoe de rval veranderd.

Offline kuifje09

  • Lid
Re: poll() ; vreemd gedrag of niet
« Reactie #2 Gepost op: 2013/06/05, 13:01:46 »
Dat was dus duidelijk een blind-spot.  fgets moet je testen tegen een NULL.  Dan gaat hij goed. Met de count na de if (retval>0) {
is het helemaal prima als test programmatje.

Nog beter, gebruik voor elke stream een andere buffer!  dezelfde buffer voor 2 streams is FOUT!
Zelfde soort test met select geeft geen goed resultaat, zelfs niet als je met select stream voor stream test, inplaats van in een keer meedere streams. Wat wel moet kunnen ( FD_SET e.d. ) Mogelijk is dit gerelateerd aan het werken met stdin en de /dev/tty .  ook al zijn de filedescriptors verschillend.

Met poll kan je op meerdere bits testen.
« Laatst bewerkt op: 2013/06/05, 14:31:49 door kuifje09 »