PDA

View Full Version : Select() Posix: grattacapo


LimiT-MaTz
20-12-2006, 21:03
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

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

int main()
{
int fd = 0;
char * value= (char *) malloc (sizeof(char) * 100);
int retval;
int len = 0;

fd_set rfds;
fd = open("/home/matz/fifo", O_RDONLY);
for(;;){
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
retval = select(fd + 1 , &rfds, NULL, NULL, NULL);
printf("retval %d\n",retval);
if (retval == -1) {
fprintf(stderr, "select failed:");
return -1;
}
else{
if (FD_ISSET(fd, &rfds)) {
len = read(fd, value, 100);
value[len]='\0';
printf("%s",value);
}
}
}
return 0;
}

/* dopo aver letto per la prima volta un dato dalla fifo ad ogni ciclo successivo continua a vedere retval = 1 e il fd registrato nell'insieme rfds */


/home/matz/fifo è una fifo.
Lancio il programmino lui entra nella select e rimane in attesa.
Un altro processo scrive sulla fifo a questo punto il "programmino" si sveglia e stampa su stdout il dato.

Fin qui tutto ok.

Ora vengono i problemi:
rinizia il ciclo riazzero l'insieme rfds inserisco fd nell'insieme entro nella select ma NON MI FERMO (nessun processo ci ha scritto sopra).

Non riesco a capire perchè cio' accada ...
Sapreste aiutarmi?

ilsensine
21-12-2006, 09:10
Hai raggiunto una condizione di EOF; puoi controllare che la read ritorna 0.

Fatti un favore, uccidi la select e usa la poll.

LimiT-MaTz
21-12-2006, 11:10
ok, accetto il tuo consiglio per quanto riguarda la poll.
int main()
{
int fd = 0;
char * value= (char *) malloc (sizeof(char) * 100);
int retval;
int len = 0;

struct pollfd p;
fd = open("/home/matz/fifo", O_RDONLY);
for(;;){
p.fd = fd;
p.events = POLLIN;
retval = poll(&p, 1, 0);
printf("retval %d\n",retval);

if (retval == -1) {
fprintf(stderr, "select failed:");
return -1;
}
else{
if(p.revents == POLLIN)
{
printf("HERE");
len = read(fd, value, 100);
value[len]='\0';
printf("%s",value);
}
}
}
return 0;
}


in output avro':

HERE
"dato ricevuto"
retval 1
retval 1
retval 1
retval 1

se vado a controllare p.revents è != da POLLIN, cio' nonostante poll() ritorna 1, nonostante in events abbia specificato solo POLLIN.

questo nn mi torna:
RETURN VALUE
On success, a positive number is returned; this is the number of structures which have non-zero revents fields (in other words, those
descriptors with events or errors reported). A value of 0 indicates that the call timed out and no file descriptors were ready. On
error, -1 is returned, and errno is set appropriately.

ilsensine
21-12-2006, 11:18
Torna, torna. Il pipe è stato chiuso dall'altro lato, e revents ritorna l'evento come POLLHUP. Gli eventi di errore vengono _sempre_ ritornati, anche se non li hai richiesti.

LimiT-MaTz
21-12-2006, 11:45
la situazione diventa problematica...
ti spiego quello che volevo fare:
un processo multitread che ascoltasse i comandi sulla pipe e in base a questi facesse delle operazioni.
La mia idea era quella di usare una fifo e leggere da questa quando si presentavano dei dati usando appunto un meccanismo (select).

Visti gli sviluppi ora non so come comportarmi.

ilsensine
21-12-2006, 12:05
Semplicemente, chiudi e riapri la pipe.

LimiT-MaTz
21-12-2006, 13:00
Semplicemente, chiudi e riapri la pipe.

argh, non ci sono ancora...

int main()
{
int fd = 0;
char * value= (char *) malloc (sizeof(char) * 100);
int retval;
int len = 0;

struct pollfd p;
fd = open("/home/matz/fifo", O_RDONLY);
for(;;){
p.fd = fd;
p.events = POLLIN;
retval = poll(&p, 1, 0);

printf("retval %d\n",retval);
if (retval == -1) {
fprintf(stderr, "select failed:");
return -1;
}
else{
if(p.revents == POLLIN){
printf("POLLIN\n");
len = read(fd, value, 100);
value[len]='\0';
printf("%s\n",value);
}
if(p.revents == POLLHUP){
printf("POLLHUP");
close(fd);
open("/home/matz/fifo", O_RDONLY);
}

}
}
return 0;
}

nulla da fare casualmente ogni tanto si looppa e spara in stdout una serie di retval 1.

ilsensine
21-12-2006, 14:46
Che casotto che hai fatto...

int main()
{
int fd;
char * value= malloc (sizeof(char) * 100);
int retval;
int len;

struct pollfd p;
p.events = POLLIN;

fd = open("/home/matz/fifo", O_RDONLY);
while(fd>=0){
p.fd = fd;
retval = poll(&p, 1, -1);

printf("retval %d\n",retval);
if (retval == -1) {
perror("poll");
return -1;
}
if(p.revents & POLLIN){
printf("POLLIN\n");
len = read(fd, value, 99);
if (len>=0) {
value[len]='\0';
printf("%s\n",value);
} else
perror("read");
} else if(p.revents & POLLHUP){
printf("POLLHUP\n");
close(fd);
fd = open("/home/matz/fifo", O_RDONLY);
}
}

perror("open");
return -1;
}

LimiT-MaTz
21-12-2006, 14:53
effettivamente ... :muro:

Grazie come al solito sei stato gentilissimo!

ilsensine
21-12-2006, 15:21
Volendo essere pignoli, c'è ancora un "piccolo" errore:

if (retval == -1) {
if (errno!=EINTR) {
perror("poll");
return -1;
}
continue;
}


La poll ritorna EINTR anche in corrispondenza di SIGSTOP+SIGCONT :muro:

trallallero
22-12-2006, 10:34
Fatti un favore, uccidi la select e usa la poll.
perché ? io l'ho usata per un progetto per la EdisonTel (2001) e sta ancora andando da quello che so

ilsensine
22-12-2006, 12:00
perché ?
Poco scalabile; interfaccia dubbia (limite di FD_SETSIZE "hardcoded" all'atto della compilazione).
La poll è pià semplice e compatta, e non è legata a quell'assurda idea degli FD_SET.

trallallero
22-12-2006, 12:48
Poco scalabile; interfaccia dubbia (limite di FD_SETSIZE "hardcoded" all'atto della compilazione).
La poll è pià semplice e compatta, e non è legata a quell'assurda idea degli FD_SET.
ero convinto di aver usato la select ma in effetti non c'entra niente :stordita:
Ho rivisto il codice, ho usato socket, accept, setsockopt...
Uff, non mi ricordo neanche piú questa roba a furia di pro*ciare e di burocrazia aziendale :muro: