[C] Probleme exec dans un fork :D

Probleme exec dans un fork :D [C] - C - Programmation

Marsh Posté le 11-12-2003 à 13:12:18    

Dites, on a besoin d'aide et on capte pas pourquoi ca déconne :D Taz va surement hurler "le code il est moche" , je l'en prie :D
 
Notre projet est un serveur web multithreadé avec support CGI.
 
Notre traitement CGI est simplifié : on file la requete intégrale http sur stdin du programme CGI et basta  ( pas de variables d'environnement a la apache et co ).
 
Donc l'architecture basique du serveur web :
-Un thread principal quié coute les requetes et les ajoute dans une liste chainée.
-X threads qui prennent en boucle ( avec force semaphores et compagnie) les "jobs" dans la liste chainée et les traitent.
 
On a pour consigne impérative de gérer les CGI avec exec ou consorts ( la je suis d'accord ) et de laisser le thread répondre a d'autres jobs sans avoir a attendre la fin d'un CGI.
 
Voici le bout de code que l'on utilise actuellement qui gère cela :
 

Code :
  1. switch(fork()) {
  2. case -1:
  3.   perror("fork error" );
  4.   break;
  5. case 0:                 /* child */
  6.   close(fdpipe[1]);
  7.   dup2(fdpipe[0],fileno(stdin) );
  8.   dup2(sc,fileno(stdout));
  9.   ftmp = open("debug",O_CREAT | O_WRONLY);
  10.   write(ftmp,"fils : avant execlp\n",strlen("fils : avant execlp\n" ));
  11.   execlp(pRes2->NomAppli, pRes2->NomAppli, pRes2->NomFic, NULL);
  12.   write(ftmp,"fils : apres execlp\n",strlen("fils : apres execlp\n" ));
  13.   close(ftmp);
  14.   close(fdpipe[0]);
  15.   close(sc);
  16.   exit (0); /* ???*/
  17.   break;
  18. default:                /* parent */
  19.   close(fdpipe[0]);
  20.   write(fdpipe[1], pReq->raw, strlen(pReq->raw));
  21.   close(fdpipe[1]);
  22.   close(sc);
  23.   (*pCUR_CGI)--;
  24.   return NULL ;
  25. }


 
PRes2->nomappli contient l'executable a lancer ( perl dans notre cas), PRes2->nomFic le nom du fichier sur lequel executer perl, et Preq->Raw la requete brute a renvoyer au CGI, sc le socket en cours.
 
Bon, vous etes arrivé la, merci de votre patience et de votre compréhension.
 
Notre problème est simple :
-Si on mets un wait(0) dans le père, ca marche nickel, la réponse est renvoyée, et YAISS c'est cool, mais le père attends que le fils se termine.
-Si on mets pas de wait(0), le pere s'execute et continue son travail sans souci ( c'est un thread); mais le fils execute le prog perl correctement, envopie la réponse... et reste en processus Zombie dans ps, et surtout n'execute rien de ce qui se trouve sous l'execlp ...
 
Vous auriez une idée sur le pourquoi du comment de ce probleme ?
 
Merci énormément :jap:
 
PS : putain d'identation de merde :heink:


Message édité par Tetedeiench le 11-12-2003 à 13:15:04
Reply

Marsh Posté le 11-12-2003 à 13:12:18   

Reply

Marsh Posté le 11-12-2003 à 13:27:38    

tetedeiench a écrit :


[...]
 
Notre problème est simple :
-Si on mets un wait(0) dans le père, ca marche nickel, la réponse est renvoyée, et YAISS c'est cool, mais le père attends que le fils se termine.
 
Vous auriez une idée sur le pourquoi du comment de ce probleme ?
 
Merci énormément :jap:
 
PS : putain d'identation de merde :heink:


 
Je suis pas certain mais essaye avec waitpid et l'option WNOHANG
 
A+

Reply

Marsh Posté le 11-12-2003 à 13:57:31    

fork() ne crée pas de threads mais des processus [:spamafote]

Reply

Marsh Posté le 11-12-2003 à 14:29:47    

salut je viens d essayer rapidement et le code derriere un execlp n est pas execute normalement( il est ecrase par le programme appele).
Maisje suis ptete pas dans le sujet...

Reply

Marsh Posté le 11-12-2003 à 14:30:50    

bah c'est plutôt normal, un exec ça ecrase le code

Reply

Marsh Posté le 11-12-2003 à 14:31:50    

chaica a écrit :

salut je viens d essayer rapidement et le code derriere un execlp n est pas execute normalement( il est ecrase par le programme appele).
Maisje suis ptete pas dans le sujet...
 

t'as peut être surtout vraiment rien comprus [:dawa]

Reply

Marsh Posté le 11-12-2003 à 14:55:36    

mettre du code apres le execlp/vp/etc équivaut à :
 
int fct()
{
 return 2;
 std::cout << "ahah\n";
}
 
le fork permet de dupliquer le programme en mémoire et le execlp remplace tout le code de la copie par le programme désiré.


---------------
«Le succès consiste à aller d'échecs en échecs sans jamais perdre son enthousiasme» - Churchill
Reply

Marsh Posté le 11-12-2003 à 14:58:27    

j'ajouterais "man execl" pour plus de compréhension [:aloy]

Reply

Marsh Posté le 11-12-2003 à 15:17:08    

Bon, OK, mais ca, limite, on s'en fout un peu ( vu que l'on doit gérer un nombre maximum de processus CGI s'executant ... ben... ).
 
Deja, dans l'architecture présente qui les gère pas, pourquoi si le pere ne fait pas de wait() le fils devient zombie ??? il devrait se terminer et point. Pire, la réponse est envoyée correctement comme avec le wait...
 
Pourquoi ?

Reply

Marsh Posté le 11-12-2003 à 15:18:28    

oui, c'est normal.

Reply

Marsh Posté le 11-12-2003 à 15:18:28   

Reply

Marsh Posté le 11-12-2003 à 15:35:05    

Merci taz. Ca nous aide vachement O_o
 
Bon sérieux, si tu pouvais détailler une de tes réponses une fois :D Comment faire continuer le père sans créer de processus zombies ( donc sans wait() directement dans le père) ?

Reply

Marsh Posté le 11-12-2003 à 15:35:31    

Ca doit avoir un lien avec SIGCHLD ça  :whistle:

Reply

Marsh Posté le 11-12-2003 à 15:38:03    

tu sais ce que c'est un zombie ?
t'es sur de pas vouloir faire des threads ?
ben quand un fils à fini, tu wait pour récupérer son statut, ça me parait normal. sinon, si tu ne wait pas pour récupérer son statut, ben par définition t'as un zombie : un processus terminé dont le père ignore la terminaison.

Reply

Marsh Posté le 11-12-2003 à 16:12:49    

pourquoi pas un waitpid à la place de wait?

Code :
  1. int status;
  2. waitpid(-1, & status, WNOHANG|WUNTRACED);


à faire dans le père de tous vos fils car -1 permet d'atteindre la fin de n'importe quel fils, alors que WHOHANG permet de ne pas bloquer (pas de fils mort/zombie? on continue le job).
Si waitpid est effectue dans un boucle while (par exemple) qui execute le fork, théoriquement, TOUS les fils qui passent en état zombie mourrons correctement
 
 
EDIT: hum... il peut avoir des zombies si votre process père est tué par un signal, pour eviter les zombies à la mort du père, il faut "installer" un handler des signaux)


Message édité par western le 11-12-2003 à 16:22:53
Reply

Marsh Posté le 11-12-2003 à 16:54:41    

Taz a écrit :

tu sais ce que c'est un zombie ?
t'es sur de pas vouloir faire des threads ?
ben quand un fils à fini, tu wait pour récupérer son statut, ça me parait normal. sinon, si tu ne wait pas pour récupérer son statut, ben par définition t'as un zombie : un processus terminé dont le père ignore la terminaison.


 
Oui, car le probleme des threads, c'est que si on fait un exec() dedans, le process sera remplacé et donc notre serveur entier executera le CGI :( Enfin si c'est possible avec des threads ca nous simplifierai énormément la vie bien sur...
 
SIGCHLD est exactement ce que nous recherchions :)

Reply

Marsh Posté le 11-12-2003 à 16:56:04    

mais c'est pas des thread bordel :o :o :o :o :o :o :o :o

Reply

Marsh Posté le 11-12-2003 à 17:02:13    

Taz a écrit :

mais c'est pas des thread bordel :o :o :o :o :o :o :o :o  


 
Tu me dis :
 

Citation :

t'es sur de pas vouloir faire des threads ?


 
Auquel je te réponds que faire un thread pour le execlp me semble un peu ... a moins que j'aieloupé quelque chose, nan :??:

Reply

Marsh Posté le 11-12-2003 à 17:09:07    

non, quand on te lis, c'est le bordel entre processus et thread. bon bref, faut que t'attrapes le dit signal et dans le gestionnaire, tu fous un wait :D.


Message édité par Taz le 11-12-2003 à 17:09:17
Reply

Marsh Posté le 11-12-2003 à 17:14:23    

Taz a écrit :

non, quand on te lis, c'est le bordel entre processus et thread. bon bref, faut que t'attrapes le dit signal et dans le gestionnaire, tu fous un wait :D.  


 
ca cai en cours de faisage ( si on m'avait pas pris mon PC avec les sources à la fac, ce serait déjà fait :D )
 
Pour les process et les threads, non, c pas le bordel, au contraire :
-Un process principal et 10 threads
-le process principal récupère les requetes HTTP et les mets dans une liste chainée ( producteur/consommateurs )
-Les threads prennent un job sur la liste chainée et le traitent en renvoyant la réponse.
-Si le thread tombe sur un CGI, alors il fork(), son fils lance un exec et lui il lui envoie la requete brute via un pipe redirigé sur stdin , et apres avir envoyé la requete est sensé continuer son job sans attendre la fin du CGI  
 
voilà :


Message édité par Tetedeiench le 11-12-2003 à 17:14:52
Reply

Marsh Posté le 11-12-2003 à 17:20:36    

t'avais déjà demande conseil à ce propos ?

Reply

Marsh Posté le 11-12-2003 à 17:21:34    

euh non, je pense pas, du moins, j'en ai pas le souvenir :/
 
Ah si, sur les semaphores !


Message édité par Tetedeiench le 11-12-2003 à 17:21:44
Reply

Marsh Posté le 11-12-2003 à 19:24:32    

je pige toujours pas l'intérêt de mettre du code derrière un execlp vu qu'il ne sera pas executé m'enfin...

Reply

Marsh Posté le 11-12-2003 à 19:37:52    

ben ça n'en a aucun. le seul code qu'on mets derrière, c'est du code à exécuter au cas ou exec échoue

Reply

Marsh Posté le 12-12-2003 à 00:19:29    

chaica a écrit :

je pige toujours pas l'intérêt de mettre du code derrière un execlp vu qu'il ne sera pas executé m'enfin...
 


 
Maintenant il a sauté et se trouve dans le code du SIGCHLD ...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed