|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
[C] Open e read su una pipe con nome
Ciao, ho un "astioso" problema che da qualche giorno mi affligge... Un processo server legge richieste da una pipe con nome la quale, prima di iniziare ad effettuare le letture, viene aperta in sola lettura. Siccome la open su una pipe e' bloccante, quando essa ritorna c'e' sicuramente un client che ha aperto la pipe stessa in scrittura e, quindi, quando il server effettuera' la read, essa:
_ o ritornera' il numero di bytes letti _ oppure risultera' a sua volta bloccante fintanto che non c'e' qualche byte da leggere. E fin qui e' proprio il comportamento che vorrei fosse tenuto dal server. L'inconveniente e': se c'e' un solo client con la pipe aperta in scrittura, quando esso, una volta ricevuta la risposta dal server, chiudera' la pipe in scrittura il server rimarra' (Non si sa quanto) con una pipe aperta in lettura senza che nessuno ce l'abbia aperta in scrittura. A questo punto ogni read che il server effettuera' ritornera' 0 senza che si abbia lo "sperato" comportamento bloccante. Siccome vorrei evitare, ovviamente, attesa attiva come potrei fare per fare in modo che, anche quando il server rimane con la pipe aperta in sola lettura (Senza che nessuno l'abbia aperta in scrittura), possa effettuare delle read bloccanti evitando attesa attiva ?!? C'e' qualche "scappatoia" o qualche soluzione logica... alla quale la mia mente bacata non ha pensato ?!? ![]() P.S.: avevo pensato di far aprire al server la pipe in modalita' scrittura/lettura in modo che l'effetto bloccante sia sempre dato dalla read (Mentre la open in scrittura/lettura sara' no bloccante). Ma non so se sia "eticamente" corretto... thks ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Una poll prima della read?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
![]() Altra domanda: avevo provato ad aprire la pipe prima in modalita' O_RDONLY (Bloccante sino a che il capo in scrittura non viene aperto da qualcuno) e subito dopo anche in modalita' O_WRONLY (Senza utilizzare il descrittore restituito ma solo per evitare che future read potessero restituire 0 come valore di ritorno). La prima lettura viene eseguita correttamente e la richiesta viene soddisfatta mentre, quando il server legge la seconda volta dalla pipe, la read restituisce -1 e la variabile errno mi urla in faccia: "Interrupted System Call". A cosa potrebbe essere dovuto !? Ad un segnale non catturato o mal gestito o a cos'altro ?! thks ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Dovresti essere sempre preparato a un EINTR. Se ti capita, devi semplicemente rieseguire la read.
EINTR viene generato ogni volta che arriva un segnale; non è un errore vero e proprio, ma una notifica.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Strano...prova a definire un signalhandler per SIGPIPE
Oppure, ancora meglio: chiudi la pipe e riaprila...credo che le pipe abbiano un comportamento un pò "particolare".
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
Aprendo prima in lettura e poi in scrittura adesso funziona. Poi ho provato con la poll ma mi da qualche problema. In particolar modo quando la pipe rimane aperta in sola lettura dal server (Poiche' il primo client l'ha chiusa in scrittura) al ciclo successivo la poll non ha effetto bloccante (Perche?!?) e stessa cosa nelle chiamate successive anche se nessun client apre e chiude la pipe in scrittura. In questo modo ogni volta viene effettuata una read che ritorna (Come atteso) 0. ![]()
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Sto dando una occhiata; stai usando dei file di tipo pipe aperti con open() oppure la syscall pipe() ?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Bene, bene...ho appena visto che la "normale" open su un pipe è _bloccante_ (nota: la open stessa, non solo la read!)
Una open con O_NONBLOCK invece non è bloccante. Inoltre sono riuscito a riprodurre il tuo problema: la poll che ritorna "1" ma la read che ritorna "0", dopo la chiusura del client. Se vai a vedere però cosa c'è nel campo "revents" della struttura della poll relativa al pipe, non c'è POLLIN, ma...16, che corrisponde a POLLHUP! In sintesi: credo che quando l'altro capo della pipe viene chiuso, devi chiudere e riaprire il file pipe.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Ad esempio questo funziona...
Codice:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/poll.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> static void __attribute__((__noreturn__)) fail(const char *s) { perror(s); exit(-1); } int main(void) { int fd; int ret; char buf[4096]; struct pollfd pfd; reopen: fd = open("pipe_name", O_RDONLY|O_NONBLOCK); if(fd<0) fail("open"); pfd.fd = fd; pfd.events = POLLIN; fprintf(stderr, "pipe aperto sul fd %d...\n", fd); retry: ret = poll(&pfd, 1, -1); fprintf(stderr, "poll=%d revents=%d\n", ret, pfd.revents); if(pfd.revents&POLLIN) { ret = read(fd, buf, 4095); fprintf(stderr, "read=%d\n", ret); if(ret<=0) goto retry; buf[ret] = '\0'; fprintf(stderr, "recv %s\n", buf); goto retry; } else if(pfd.revents&POLLHUP) { fprintf(stderr, "Hangup!\n"); close(fd); goto reopen; } else { fprintf(stderr, "!?\n"); goto retry; } return 0; }
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#13 | |||
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Quote:
Quello che controllo è "revents", ovvero lo stato del pipe. Quote:
Nel tuo caso stai anche qui attento a EINTR.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|||
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Per attesa attiva indico la situazione nella quale si e' in attesa del verificarsi di un evento e, invece, di attendere che l'evento venga in qualche modo segnalato si continuano a fare delle chiamate (Che sprecano risorse) per capire se l'evento si e' verificato.
Tu controlli il valore di ritorno della read (Mi ero sbagliato nel dire che poll al posto di read ![]() _-1 in caso d'errore (Ed errno settata) _>0 altrimenti Il fatto che venga fatta dopo una poll "impedisce" che la read restituisca un valore = 0. Il comportamento a quel punto dovrebbe essere bloccante. Mentre a me succede proprio questo ovvero la read mi restituisce 0 pur essendo chiamata dopo una poll.
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. Ultima modifica di Ed_Bunker : 26-07-2004 alle 15:40. |
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Utilizzo di risorse zero
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
Boh...
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#18 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
Return Value: On success, a positive number is returned, where the number returned 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 have been selected. On error, -1 is returned, and errno is set appropriately.
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
![]()
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
![]() |
![]() |
![]() |
#20 | |
Senior Member
Iscritto dal: Jan 2004
Città: Montignoso(MS)
Messaggi: 9448
|
Quote:
![]() Comunque ora e' ok. Penso il comportamento anomalo derivasse ancora dall'errore che avevo commesso nelle sigaction.
__________________
"Il Meglio che si possa ottenere è evitare il peggio." I.C. |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 08:29.