OVH Cloud OVH Cloud

tube nomme et shells

10 réponses
Avatar
Hervé Autret
Bonjour,

Je ne comprends pas ce qui se passe dans le cas suivant :
Je cree un tube remanent je lance un sous-shell pour écrire en boucle
dans ce tube. L'écrivain est alors en attente.

$ mknod ~/tmp/tube.toto p
$ (while true; do echo "un
deux
trois
"> ~/tmp/tube.toto ; done)

Ensuite, on peut lire indéfiniment dans ce tube, (cat ~/tmp/tube.toto)
jusqu'à ce qu'on arrête le lecteur, auquel cas l'écrivain s'arrête
aussi.

Mais si je lance cat ~/tmp/tube.toto avant de lancer l'écrivain, cat lit
une fois l'itération et s'arrête, mais l'écrivain ne s'arrête pas et
reste en attente (on peut encore le lire).

Les autres shells se comportent avec des différences, lorsque je lance
cat sur le tube vide :

- tcsh : il faut le relancer deux fois pour voir le tube débiter
indéfiniment.

- csh : marche souvent, mais parfois débite une centaine de lignes et
s'arrête, avec l'écrivain en attente.

- zsh : débit normal presque toujours sauf lors d'une session, où
il s'est comporté systématiquement comme bash.

- ksh : comme zsh

Quelqu'un saurait-il le pourquoi de ce comportement, et quelle page de man
j'aurais dû ouvrir avant de poster ? j'utilise le kernel 2.4, j'ai testé
dans xterm, rxvt et la console, au cas où...
--
Hervé

10 réponses

Avatar
Nicolas George
Hervé Autret wrote in message
:
Je ne comprends pas ce qui se passe dans le cas suivant :
Je cree un tube remanent je lance un sous-shell pour écrire en boucle
dans ce tube. L'écrivain est alors en attente.

$ mknod ~/tmp/tube.toto p
$ (while true; do echo "un
deux
trois
"> ~/tmp/tube.toto ; done)

Ensuite, on peut lire indéfiniment dans ce tube, (cat ~/tmp/tube.toto)
jusqu'à ce qu'on arrête le lecteur, auquel cas l'écrivain s'arrête
aussi.

Mais si je lance cat ~/tmp/tube.toto avant de lancer l'écrivain, cat lit
une fois l'itération et s'arrête, mais l'écrivain ne s'arrête pas et
reste en attente (on peut encore le lire).


C'est un problème de timing fin : si cat essaie de lire pendant que le shell
fait le while et pas pendant l'echo lui-même, il constate que le tube est
fermé à l'autre bout et s'interrompt. Tu ne peux en aucun cas compter sur
tel ou tel comportement, n'importe quoi peut arriver selon le shell, les
paramètres de scheduling, la charge de la machine, le sens du vent, etc.

Fu2 où de droit.

Avatar
lhabert
Hervé Autret :

$ mknod ~/tmp/tube.toto p
$ (while true; do echo "un
deux
trois
"> ~/tmp/tube.toto ; done)

Ensuite, on peut lire indéfiniment dans ce tube, (cat ~/tmp/tube.toto)


Je crois que tu es dans les race-conditions jusqu'au cou.

Une tentative de lecture sur un pipe vers l'entrée duquel plus aucun process
n'a de fd va renvoyer un EOF (en l'occurence, le cat lecteur doit alors se
terminer). Mais il suffit que ton cat lecteur ne fasse jamais ses read entre
le moment où l'écrivain ferme le pipe et le rouvre au tour de boucle suivant
pour que tout se passe comme tu le décris. D'ailleurs, chez moi, le cat
lecteur fini par s'arrêter au bout d'un nombre variable de tours de boucle
de la part de l'écrivain, comme quoi ça finit par tomber au mauvais
moment...

jusqu'à ce qu'on arrête le lecteur, auquel cas l'écrivain s'arrête aussi.


Là, il y a encore une question de timing :
- si tu arrêtes le lecteur entre la fin d'un « echo ... > tube.toto » et le
début du suivant, l'écrivain va se mettre à bloquer lorsqu'il va, au tour de
boucle suivant tenter de réouvrir le pipe
- si tu arrêtes le lecteur pendant que l'écrivain est en-train d'écrire, ce
dernier se prend un SIGPIPE. Maintenant, le shell en question peut réagir de
différentes manières à ce SIGPIPE, ce qui doit expliquer les différences de
comportement entre shells que tu signales. Chez moi, le bash interactif
meurt carrément quand il se prend le SIGPIPE.

Mais si je lance cat ~/tmp/tube.toto avant de lancer l'écrivain, cat lit
une fois l'itération et s'arrête, mais l'écrivain ne s'arrête pas et
reste en attente (on peut encore le lire).


Là, tu dois tomber dans le premier cas mentionné ci-dessus. Je n'ai aucune
idée de comment ça se fait qu'on tombe dans un cas suivant qu'on lance
l'écrivain avant ou après. C'est assez bizarre, si ça se trouve je rate
quelque chose.

Quelqu'un saurait-il le pourquoi de ce comportement, et quelle page de man
j'aurais dû ouvrir avant de poster ?


pipe(7)

Avatar
Hervé Autret
Bonjour,


chez moi, le cat lecteur fini par s'arrêter au bout d'un nombre
variable de tours de boucle


J'ai fini par observer ça aussi; un nombre très variable... Donc Ok, va
pour les accès concurrents.

Chez moi, le bash interactif meurt carrément quand il se prend le
SIGPIPE.


Chez moi aussi, c'est pourquoi la commande est entre parenthèses.
Quand le sous-shell meurt il n'entraîne pas le shell avec lui, et
l'historique est sauvegardé; pas besoin d'ouvrir une nouvelle fenêtre
pour chaque essai.

on tombe dans un cas suivant qu'on lance l'écrivain avant ou après.
C'est assez bizarre, si ça se trouve je rate quelque chose.


Pour ça, je réponds aussi NG sur fcou.

pipe(7)


Pas de ça chez loi ;) man pipe renvoie au man 2, qui ne soncerne pas les
tubes rémanents. Sous Mandriva 2006, j'ai même ça :
The pipe(8) daemon processes requests from the Postfix queue manager
postfix n'étant pas installé...

à +
--
Hervé

Avatar
Hervé Autret
Bonjour,


chez moi, le cat lecteur fini par s'arrêter au bout d'un nombre
variable de tours de boucle


J'ai fini par observer ça aussi; un nombre très variable... Donc Ok, va
pour les accès concurrents.

Chez moi, le bash interactif meurt carrément quand il se prend le
SIGPIPE.


Chez moi aussi, c'est pourquoi la commande est entre parenthèses.
Quand le sous-shell meurt il n'entraîne pas le shell avec lui, et
l'historique est sauvegardé; pas besoin d'ouvrir une nouvelle fenêtre
pour chaque essai.

on tombe dans un cas suivant qu'on lance l'écrivain avant ou après.
C'est assez bizarre, si ça se trouve je rate quelque chose.


Pour ça, je réponds aussi NG sur fcou.

pipe(7)


Pas de ça chez moi ;) man pipe renvoie au man 2, qui ne soncerne pas les
tubes rémanents. Sous Mandriva 2006, j'ai même ça :
The pipe(8) daemon processes requests from the Postfix queue manager
postfix n'étant pas installé...

à +

Avatar
lhabert
Hervé Autret :

pipe(7)


Pas de ça chez moi ;)


Bah ça doit être planqué dans un package non installé...


Avatar
Hervé Autret
Bonsoir

Luc Habert posta :

Bah ça doit être planqué dans un package non installé...


$ man fifo
...
SEE ALSO
mkfifo(3), mkfifo(1), pipe(2), socketpair(2), open(2), signal(2), sigaction(2)

Non installé et relativement méconnu, qui plus est.
--
Hervé

Avatar
Jean Marc
Bjr,

Si côté client on fait :
(while true; do cat /tmp/tube.toto ;done)
ça fonctionne parfaitement, j'ai utilisé la commande mkfifo (je préfère)
des fois que ..

"Luc Habert" a écrit dans le message de news:
drbtpk$285i$
Hervé Autret :

$ mknod ~/tmp/tube.toto p
$ (while true; do echo "un
deux
trois
"> ~/tmp/tube.toto ; done)

Ensuite, on peut lire indéfiniment dans ce tube, (cat ~/tmp/tube.toto)


Je crois que tu es dans les race-conditions jusqu'au cou.

Une tentative de lecture sur un pipe vers l'entrée duquel plus aucun
process

n'a de fd va renvoyer un EOF (en l'occurence, le cat lecteur doit alors se
terminer). Mais il suffit que ton cat lecteur ne fasse jamais ses read
entre

le moment où l'écrivain ferme le pipe et le rouvre au tour de boucle
suivant

pour que tout se passe comme tu le décris. D'ailleurs, chez moi, le cat
lecteur fini par s'arrêter au bout d'un nombre variable de tours de boucle
de la part de l'écrivain, comme quoi ça finit par tomber au mauvais
moment...

jusqu'à ce qu'on arrête le lecteur, auquel cas l'écrivain s'arrête
aussi.



Là, il y a encore une question de timing :
- si tu arrêtes le lecteur entre la fin d'un « echo ... > tube.toto » et
le

début du suivant, l'écrivain va se mettre à bloquer lorsqu'il va, au tour
de

boucle suivant tenter de réouvrir le pipe
- si tu arrêtes le lecteur pendant que l'écrivain est en-train d'écrire,
ce

dernier se prend un SIGPIPE. Maintenant, le shell en question peut réagir
de

différentes manières à ce SIGPIPE, ce qui doit expliquer les différences
de

comportement entre shells que tu signales. Chez moi, le bash interactif
meurt carrément quand il se prend le SIGPIPE.

Mais si je lance cat ~/tmp/tube.toto avant de lancer l'écrivain, cat lit
une fois l'itération et s'arrête, mais l'écrivain ne s'arrête pas et
reste en attente (on peut encore le lire).


Là, tu dois tomber dans le premier cas mentionné ci-dessus. Je n'ai aucune
idée de comment ça se fait qu'on tombe dans un cas suivant qu'on lance
l'écrivain avant ou après. C'est assez bizarre, si ça se trouve je rate
quelque chose.

Quelqu'un saurait-il le pourquoi de ce comportement, et quelle page de
man


j'aurais dû ouvrir avant de poster ?


pipe(7)



Avatar
lhabert
Ah bein moi j'ai pipe(7) dans la liste. Ne pas chercher à comprendre...
Avatar
lhabert
"Jean Marc" :

(while true; do cat /tmp/tube.toto ;done)
ça fonctionne parfaitement,


Oui, forcément. Enfin la bonne solution est de faire le « >tube.toto » en
dehors de la boucle de l'écrivain, comme il a été suggéré sur fcou.

j'ai utilisé la commande mkfifo (je préfère) des fois que ..


C'est rigoureusement équivalent.

Avatar
Sébastien Monbrun aka TiChou
Dans le message <news:drfjvd$2b13$,
*Luc Habert* tapota sur f.c.o.l.configuration :

Ah bein moi j'ai pipe(7) dans la liste. Ne pas chercher à comprendre...


Mais on peut chercher à trouver l'origine de ce fichier ? :-)

$ dpkg -S /usr/share/man/man7/pipe.7*

$ qpkg -f /usr/share/man/man7/pipe.7*

$ rpm -qf /usr/share/man/man7/pipe.7*

--
Sébastien Monbrun aka TiChou