Je viens de trouver un bug sournois dans un de mes programmes écrit
en C et en lisant la page man de read() [Solaris], je m'aperçois
avec horreur que lorsque je lis dans un pipe, la fonction read()
peut être interrompue et que le read() peut s'arrêter avant d'avoir
lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et
de signaux. Comment s'arranger pour que les appels read() ne soient
pas interrompus par des signaux, donc que le contenu de mon buffer
soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre
valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela
des signaux à temps réel).
Le code doit pouvoir tourner sous Solaris et au moins Linux et je ne
vois pas vraiment par où commencer...
Cordialement,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Aris
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED. Il n'y a malheureusement pas moyen de le faire de façon atomique mais ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de l'autre coté. Un solution pourait de faire du complete_read() (le read avec la boucle) une fonction critique et de desactiver les signaux en entrant pour les réactiver en sortant, auquel cas en cas de signal le signal sera catché après le read.
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre
valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela
des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED.
Il n'y a malheureusement pas moyen de le faire de façon atomique mais
ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un
write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de
l'autre coté.
Un solution pourait de faire du complete_read() (le read avec la boucle)
une fonction critique et de desactiver les signaux en entrant pour les
réactiver en sortant, auquel cas en cas de signal le signal sera catché
après le read.
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED. Il n'y a malheureusement pas moyen de le faire de façon atomique mais ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de l'autre coté. Un solution pourait de faire du complete_read() (le read avec la boucle) une fonction critique et de desactiver les signaux en entrant pour les réactiver en sortant, auquel cas en cas de signal le signal sera catché après le read.
JKB
Le 22-01-2008, à propos de Re: read() et signaux, Aris écrivait dans fr.comp.lang.c :
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED. Il n'y a malheureusement pas moyen de le faire de façon atomique mais ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de l'autre coté.
Ça, je veux bien.
Un solution pourait de faire du complete_read() (le read avec la boucle) une fonction critique et de desactiver les signaux en entrant pour les réactiver en sortant, auquel cas en cas de signal le signal sera catché après le read.
Le problème, c'est que d'après la page man, on peut récupérer deux fonctionnements :
POSIX permet à un read() interrompu par un signal de renvoyer soit le nombre doctets lus à ce point, soit -1, et de placer errno à EINTR.
J'ai l'impression que le même problème existe avec write()...
Cordialement,
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.
Le 22-01-2008, à propos de
Re: read() et signaux,
Aris écrivait dans fr.comp.lang.c :
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre
valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela
des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED.
Il n'y a malheureusement pas moyen de le faire de façon atomique mais
ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un
write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de
l'autre coté.
Ça, je veux bien.
Un solution pourait de faire du complete_read() (le read avec la boucle)
une fonction critique et de desactiver les signaux en entrant pour les
réactiver en sortant, auquel cas en cas de signal le signal sera catché
après le read.
Le problème, c'est que d'après la page man, on peut récupérer deux
fonctionnements :
POSIX permet à un read() interrompu par un signal de renvoyer soit
le nombre doctets lus à ce point, soit -1, et de placer errno à EINTR.
J'ai l'impression que le même problème existe avec write()...
Cordialement,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Le 22-01-2008, à propos de Re: read() et signaux, Aris écrivait dans fr.comp.lang.c :
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Cordialement,
JKB
il faut boucler sur le read tant que E_ERRNO est égal à E_INTERRUPTED. Il n'y a malheureusement pas moyen de le faire de façon atomique mais ça, ça n'a jamais été un secret (il n'est nullement garanti qu'après un write de x bytes dans un pipe, on puisse lire x bytes d'un seul coup de l'autre coté.
Ça, je veux bien.
Un solution pourait de faire du complete_read() (le read avec la boucle) une fonction critique et de desactiver les signaux en entrant pour les réactiver en sortant, auquel cas en cas de signal le signal sera catché après le read.
Le problème, c'est que d'après la page man, on peut récupérer deux fonctionnements :
POSIX permet à un read() interrompu par un signal de renvoyer soit le nombre doctets lus à ce point, soit -1, et de placer errno à EINTR.
J'ai l'impression que le même problème existe avec write()...
Cordialement,
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.
espie
In article , JKB wrote:
Bonjour à tous,
Je viens de trouver un bug sournois dans un de mes programmes écrit en C et en lisant la page man de read() [Solaris], je m'aperçois avec horreur que lorsque je lis dans un pipe, la fonction read() peut être interrompue et que le read() peut s'arrêter avant d'avoir lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et de signaux. Comment s'arranger pour que les appels read() ne soient pas interrompus par des signaux, donc que le contenu de mon buffer soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront pas coupes en petit morceau.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre interrompu est une solution. Gerer EINTR en est une autre. sigprocmask() pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture de ton programme...
In article <slrnfpbtme.kvi.knatschke@fermat.systella.fr>,
JKB <wilhelm-siegfried.knatschke-koenigsberg@chezmoi.com> wrote:
Bonjour à tous,
Je viens de trouver un bug sournois dans un de mes programmes écrit
en C et en lisant la page man de read() [Solaris], je m'aperçois
avec horreur que lorsque je lis dans un pipe, la fonction read()
peut être interrompue et que le read() peut s'arrêter avant d'avoir
lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et
de signaux. Comment s'arranger pour que les appels read() ne soient
pas interrompus par des signaux, donc que le contenu de mon buffer
soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre
valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela
des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes
pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie
que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere
atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront
pas coupes en petit morceau.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre
interrompu est une solution. Gerer EINTR en est une autre. sigprocmask()
pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer
que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture
de ton programme...
Je viens de trouver un bug sournois dans un de mes programmes écrit en C et en lisant la page man de read() [Solaris], je m'aperçois avec horreur que lorsque je lis dans un pipe, la fonction read() peut être interrompue et que le read() peut s'arrêter avant d'avoir lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et de signaux. Comment s'arranger pour que les appels read() ne soient pas interrompus par des signaux, donc que le contenu de mon buffer soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront pas coupes en petit morceau.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre interrompu est une solution. Gerer EINTR en est une autre. sigprocmask() pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture de ton programme...
JKB
Le 22-01-2008, à propos de Re: read() et signaux, Marc Espie écrivait dans fr.comp.lang.c :
In article , JKB wrote:
Bonjour à tous,
Je viens de trouver un bug sournois dans un de mes programmes écrit en C et en lisant la page man de read() [Solaris], je m'aperçois avec horreur que lorsque je lis dans un pipe, la fonction read() peut être interrompue et que le read() peut s'arrêter avant d'avoir lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et de signaux. Comment s'arranger pour que les appels read() ne soient pas interrompus par des signaux, donc que le contenu de mon buffer soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront pas coupes en petit morceau.
Tiens, je ne connaissais pas. Je vais creuser le truc pour envoyer de façon fiable mes informations par groupes d'au plus PIPE_BUF octets. L'essentiel pour moi est d'avoir une transmission fiable. Qu'elle soit interrompue ou non ne change rien à l'affaire pourvu que tout arrive.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre interrompu est une solution. Gerer EINTR en est une autre. sigprocmask() pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture de ton programme...
Je n'ai pas trop envie d'entrer dans les détails, parce que le programme est comment dire ? long !...
Merci,
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.
Le 22-01-2008, à propos de
Re: read() et signaux,
Marc Espie écrivait dans fr.comp.lang.c :
In article <slrnfpbtme.kvi.knatschke@fermat.systella.fr>,
JKB <wilhelm-siegfried.knatschke-koenigsberg@chezmoi.com> wrote:
Bonjour à tous,
Je viens de trouver un bug sournois dans un de mes programmes écrit
en C et en lisant la page man de read() [Solaris], je m'aperçois
avec horreur que lorsque je lis dans un pipe, la fonction read()
peut être interrompue et que le read() peut s'arrêter avant d'avoir
lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et
de signaux. Comment s'arranger pour que les appels read() ne soient
pas interrompus par des signaux, donc que le contenu de mon buffer
soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre
valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela
des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes
pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie
que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere
atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront
pas coupes en petit morceau.
Tiens, je ne connaissais pas. Je vais creuser le truc pour envoyer
de façon fiable mes informations par groupes d'au plus PIPE_BUF
octets. L'essentiel pour moi est d'avoir une transmission fiable.
Qu'elle soit interrompue ou non ne change rien à l'affaire pourvu
que tout arrive.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre
interrompu est une solution. Gerer EINTR en est une autre. sigprocmask()
pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer
que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture
de ton programme...
Je n'ai pas trop envie d'entrer dans les détails, parce que le
programme est comment dire ? long !...
Merci,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Le 22-01-2008, à propos de Re: read() et signaux, Marc Espie écrivait dans fr.comp.lang.c :
In article , JKB wrote:
Bonjour à tous,
Je viens de trouver un bug sournois dans un de mes programmes écrit en C et en lisant la page man de read() [Solaris], je m'aperçois avec horreur que lorsque je lis dans un pipe, la fonction read() peut être interrompue et que le read() peut s'arrêter avant d'avoir lu le nombre de caractères demandés.
Problème : je synchronise plusieurs processus à l'aide de pipes et de signaux. Comment s'arranger pour que les appels read() ne soient pas interrompus par des signaux, donc que le contenu de mon buffer soit celui attendu ?
En d'autres termes, j'aimerais qu'une ligne comme :
read(pipe, buffer, longueur)s
ne renvoie que 0, -1 ou longueur à l'exclusion de toute autre valeur. Je sèche un peu (d'autant plus que j'utilise derrière cela des signaux à temps réel).
Par essence, tu ne pourras pas. Mais tu as des garanties largement suffisantes pour le fonctionnement de programmes correctement ecrits.
Tu as une constante (PIPE_BUF) qui vaut au moins 512, avec comme garantie que toute ecriture dans un pipe de longueur <= PIPE_BUF se fera de maniere atomique. Par exemple, si tu as plusieurs ecrivains, leurs messages ne seront pas coupes en petit morceau.
Tiens, je ne connaissais pas. Je vais creuser le truc pour envoyer de façon fiable mes informations par groupes d'au plus PIPE_BUF octets. L'essentiel pour moi est d'avoir une transmission fiable. Qu'elle soit interrompue ou non ne change rien à l'affaire pourvu que tout arrive.
Pour tes appels read, l'utilisation de sigaction() pour eviter d'etre interrompu est une solution. Gerer EINTR en est une autre. sigprocmask() pour proteger une section critique est la 3e.
Si on veut faire quelque chose de propre, il faut de toutes facons supposer que tu auras a faire plusieurs read() jusqu'a obtenir un message complet.
Je ne peux pas te donner plus d'info sans en savoir plus sur l'architecture de ton programme...
Je n'ai pas trop envie d'entrer dans les détails, parce que le programme est comment dire ? long !...
Merci,
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.