J'ai besoin de réaliser un programme qui fait ceci:
- initialisation
- fork()
- le père s'endort
- le fils fait un certain boulot, prévient le père puis s'endort
- le père fait sa part de boulot et meurt
- le fils continue à dormir jusqu'à ce qu'on le réveille
J'ai fait ça comme ça (en simplifiant) :
newpid = fork();
if (newpid == 0) {
/* fils */
boulot1();
kill(getppid(), SIGUSR1);
pause();
}
else {
/* père */
pause();
boulot2();
exit(0);
}
Ça marche. Mais en y réfléchissant, il y a une "race condition".
Le signal USR1 peut arriver avant que le père soit en pause.
Auquel cas, je suis foutu.
Disons que dans 99,999999% des cas, le fils passera plusieurs
secondes dans boulot1 et donc je suis sauvé.
Mais je voudrais être perfectionniste. J'ai pensé à diverses
méthodes pour résoudre ce problème (par exemple en utilisant
le filesystem) mais toutes choque mon sens de l'esthétique.
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
Nicolas George
Petit Grasshopper wrote in message :
Ça marche. Mais en y réfléchissant, il y a une "race condition". Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Classique, avec les signaux spécialement. Heureusement, les versions modernes d'Unix proposent des solutions. Ici, la solution s'appelle sigsuspend : c'est pause, mais avec un changement atomique du masque de signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le démasquer dans le sigsuspend.
Petit Grasshopper wrote in message
<UaadncKYUIgi7g_ZRVnyjw@giganews.com>:
Ça marche. Mais en y réfléchissant, il y a une "race condition".
Le signal USR1 peut arriver avant que le père soit en pause.
Auquel cas, je suis foutu.
Classique, avec les signaux spécialement. Heureusement, les versions
modernes d'Unix proposent des solutions. Ici, la solution s'appelle
sigsuspend : c'est pause, mais avec un changement atomique du masque de
signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le
démasquer dans le sigsuspend.
Ça marche. Mais en y réfléchissant, il y a une "race condition". Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Classique, avec les signaux spécialement. Heureusement, les versions modernes d'Unix proposent des solutions. Ici, la solution s'appelle sigsuspend : c'est pause, mais avec un changement atomique du masque de signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le démasquer dans le sigsuspend.
lhabert
Petit Grasshopper :
Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Tu peux faire un sigprocmask avant le fork pour bloquer le signal le temps que le père se mette en pause.
Enfin personellement j'aurais plutôt relié le père au fils par un pipe, le fils écrit un caractère dans le pipe, et le père, en guise de pause lit (en mode bloquant) un caractère sur le pipe.
Petit Grasshopper :
Le signal USR1 peut arriver avant que le père soit en pause.
Auquel cas, je suis foutu.
Tu peux faire un sigprocmask avant le fork pour bloquer le signal le temps
que le père se mette en pause.
Enfin personellement j'aurais plutôt relié le père au fils par un pipe, le
fils écrit un caractère dans le pipe, et le père, en guise de pause lit (en
mode bloquant) un caractère sur le pipe.
Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Tu peux faire un sigprocmask avant le fork pour bloquer le signal le temps que le père se mette en pause.
Enfin personellement j'aurais plutôt relié le père au fils par un pipe, le fils écrit un caractère dans le pipe, et le père, en guise de pause lit (en mode bloquant) un caractère sur le pipe.
Harpo
Petit Grasshopper wrote:
Bonjour,
J'ai besoin de réaliser un programme qui fait ceci: - initialisation - fork() - le père s'endort - le fils fait un certain boulot, prévient le père puis s'endort - le père fait sa part de boulot et meurt - le fils continue à dormir jusqu'à ce qu'on le réveille
IPC ?
-- http://patrick.davalan.free.fr/
Petit Grasshopper wrote:
Bonjour,
J'ai besoin de réaliser un programme qui fait ceci:
- initialisation
- fork()
- le père s'endort
- le fils fait un certain boulot, prévient le père puis s'endort
- le père fait sa part de boulot et meurt
- le fils continue à dormir jusqu'à ce qu'on le réveille
J'ai besoin de réaliser un programme qui fait ceci: - initialisation - fork() - le père s'endort - le fils fait un certain boulot, prévient le père puis s'endort - le père fait sa part de boulot et meurt - le fils continue à dormir jusqu'à ce qu'on le réveille
IPC ?
-- http://patrick.davalan.free.fr/
Pascal Bourguignon
Petit Grasshopper writes:
Bonjour,
J'ai besoin de réaliser un programme qui fait ceci: - initialisation - fork() - le père s'endort - le fils fait un certain boulot, prévient le père puis s'endort - le père fait sa part de boulot et meurt - le fils continue à dormir jusqu'à ce qu'on le réveille
J'ai fait ça comme ça (en simplifiant) :
newpid = fork(); if (newpid == 0) { /* fils */ boulot1(); kill(getppid(), SIGUSR1); pause(); } else { /* père */ pause(); boulot2(); exit(0); }
Ça marche. Mais en y réfléchissant, il y a une "race condition". Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Disons que dans 99,999999% des cas, le fils passera plusieurs secondes dans boulot1 et donc je suis sauvé.
Mais je voudrais être perfectionniste. J'ai pensé à diverses méthodes pour résoudre ce problème (par exemple en utilisant le filesystem) mais toutes choque mon sens de l'esthétique.
Comme dit Harpo, IPC. Dans ce cas, un simple pipe devrait faire l'affaire:
int f2p[2]; check_result(pipe(f2p)); childpid=fork(); switch(childpid){ case -1: perror("fork"); exit(1); break; case 0: /* fils */ close(f2p[0]); boulot1(); { char buffer=1;int res;while(0==(res=write(f2p[1],&buffer,1))); if(res<0){perror("write");exit(1);} } close(f2p[1]); pause(); exit(0); break; default: /* père */ close(f2p[1]); {char buffer;int res;while(0==(res=read(f2p[0],&buffer,1))); if(res<0){perror("write");exit(1);}} close(f2p[0]); pause(); boulot2(); exit(0); break; }
"By filing this bug report you have challenged the honor of my family. Prepare to die!"
Petit Grasshopper <pg@quelque-part.invalid> writes:
Bonjour,
J'ai besoin de réaliser un programme qui fait ceci:
- initialisation
- fork()
- le père s'endort
- le fils fait un certain boulot, prévient le père puis s'endort
- le père fait sa part de boulot et meurt
- le fils continue à dormir jusqu'à ce qu'on le réveille
J'ai fait ça comme ça (en simplifiant) :
newpid = fork();
if (newpid == 0) {
/* fils */
boulot1();
kill(getppid(), SIGUSR1);
pause();
}
else {
/* père */
pause();
boulot2();
exit(0);
}
Ça marche. Mais en y réfléchissant, il y a une "race condition".
Le signal USR1 peut arriver avant que le père soit en pause.
Auquel cas, je suis foutu.
Disons que dans 99,999999% des cas, le fils passera plusieurs
secondes dans boulot1 et donc je suis sauvé.
Mais je voudrais être perfectionniste. J'ai pensé à diverses
méthodes pour résoudre ce problème (par exemple en utilisant
le filesystem) mais toutes choque mon sens de l'esthétique.
Comme dit Harpo, IPC. Dans ce cas, un simple pipe devrait faire
l'affaire:
int f2p[2];
check_result(pipe(f2p));
childpid=fork();
switch(childpid){
case -1:
perror("fork");
exit(1);
break;
case 0:
/* fils */
close(f2p[0]);
boulot1();
{ char buffer=1;int res;while(0==(res=write(f2p[1],&buffer,1)));
if(res<0){perror("write");exit(1);} }
close(f2p[1]);
pause();
exit(0);
break;
default:
/* père */
close(f2p[1]);
{char buffer;int res;while(0==(res=read(f2p[0],&buffer,1)));
if(res<0){perror("write");exit(1);}}
close(f2p[0]);
pause();
boulot2();
exit(0);
break;
}
J'ai besoin de réaliser un programme qui fait ceci: - initialisation - fork() - le père s'endort - le fils fait un certain boulot, prévient le père puis s'endort - le père fait sa part de boulot et meurt - le fils continue à dormir jusqu'à ce qu'on le réveille
J'ai fait ça comme ça (en simplifiant) :
newpid = fork(); if (newpid == 0) { /* fils */ boulot1(); kill(getppid(), SIGUSR1); pause(); } else { /* père */ pause(); boulot2(); exit(0); }
Ça marche. Mais en y réfléchissant, il y a une "race condition". Le signal USR1 peut arriver avant que le père soit en pause. Auquel cas, je suis foutu.
Disons que dans 99,999999% des cas, le fils passera plusieurs secondes dans boulot1 et donc je suis sauvé.
Mais je voudrais être perfectionniste. J'ai pensé à diverses méthodes pour résoudre ce problème (par exemple en utilisant le filesystem) mais toutes choque mon sens de l'esthétique.
Comme dit Harpo, IPC. Dans ce cas, un simple pipe devrait faire l'affaire:
int f2p[2]; check_result(pipe(f2p)); childpid=fork(); switch(childpid){ case -1: perror("fork"); exit(1); break; case 0: /* fils */ close(f2p[0]); boulot1(); { char buffer=1;int res;while(0==(res=write(f2p[1],&buffer,1))); if(res<0){perror("write");exit(1);} } close(f2p[1]); pause(); exit(0); break; default: /* père */ close(f2p[1]); {char buffer;int res;while(0==(res=read(f2p[0],&buffer,1))); if(res<0){perror("write");exit(1);}} close(f2p[0]); pause(); boulot2(); exit(0); break; }
"By filing this bug report you have challenged the honor of my family. Prepare to die!"
Petit Grasshopper
Nicolas George wrote:
Classique, avec les signaux spécialement. Heureusement, les versions modernes d'Unix proposent des solutions. Ici, la solution s'appelle sigsuspend : c'est pause, mais avec un changement atomique du masque de signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le démasquer dans le sigsuspend.
Oups ! La honte ! Je connaissais sigsuspend, même que j'ai déjà utilisé par le passé. Mais la programmation Unix ça doit pas être comme le vélo : on arrête quelques années et on oublie.
Un grand merci quand même.
A+
Nicolas George wrote:
Classique, avec les signaux spécialement. Heureusement, les versions
modernes d'Unix proposent des solutions. Ici, la solution s'appelle
sigsuspend : c'est pause, mais avec un changement atomique du masque de
signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le
démasquer dans le sigsuspend.
Oups ! La honte ! Je connaissais sigsuspend, même que j'ai déjà
utilisé par le passé. Mais la programmation Unix ça doit pas être
comme le vélo : on arrête quelques années et on oublie.
Classique, avec les signaux spécialement. Heureusement, les versions modernes d'Unix proposent des solutions. Ici, la solution s'appelle sigsuspend : c'est pause, mais avec un changement atomique du masque de signaux. Il suffit donc de masquer USR1 avant de lancer le fils, et de le démasquer dans le sigsuspend.
Oups ! La honte ! Je connaissais sigsuspend, même que j'ai déjà utilisé par le passé. Mais la programmation Unix ça doit pas être comme le vélo : on arrête quelques années et on oublie.