beenden von prozessen nach fork



  • ich habe einen parallelen server geschrieben.
    die kommunikation ueber die sockets funktioniert ohne probleme.
    mein problem liegt darin, dass der nebenlaeufige serverprozess,
    also der mit dem client redet (aus: unterhalte_dich_mit)
    erst beendet wird, wenn der server-haupt-prozess beendet wird.

    starte ich z.B. 2 clients die mit dem server reden, so sind auch nach
    der "unterhaltung" weiterhin 3 server aktiv.
    ein ps zeigt mir 3 server prozesse an, 2 werden als "defunct" bezeichnet.

    was bedeutet "defunct"?
    wie kann ich meine mit fork erzeugten prozesse beenden??

    also das ganze sieht etwa so aus:

    ...
    while ( 1 )
    {
      s=accept(...)
    
      pid=fork();
      switch( pid )
        case 0: /* kindprozess: beende dich nach unterhaltung mit exit */
          unterhalte_dich_mit( s ); break;
        default:
          break; /* hauptprozess "hoere" weiter am port */
    ...
    }
    
    unterhalte_dich_mit(int s)
    {
    ...
    
      close( s );
      exit( 0 );
    }
    


  • Du hast Zombie geschaffen.
    Zs sind Child Prozesse, deren Parent sich beendet hat und nicht auf die Beendigung seiner Childs gewartet hat. Die Prozesse sind zwar "tot" (erzeugen keine Load mehr), aber in der Kernelprozesstabelle sind sie nich vorhanden (man kann sie auch nicht mit einem Signal killen)

    Mach mal folgendes

    [.......]
    
    signal(SIGCHLD, sigchld_handler)
    
    [.....]
    
    void sigchld_handler(int s)
        {
            while(wait(NULL) > 0);
        }
    

    Immer, wenn sich ein Client beendet, bekommt der Vaterprozess ein SIGCHLD geschickt. Du machst dann nichts weiter, auf die Terminierung des Kindprozesses zu warten.
    Am client code ist keine Modifizierung nötig.



  • ok. danke fuer die hilfe es sieht jetzt schon besser aus.
    nur noch etwas zum verstaendnis.
    bitte nur ja wenn ich es richtig verstanden hab, sonst
    eine erklaerung, was ich falsch verstanden hab 😃

    1. der haupt-prozess kann weiterhin mehrere kinder erzeugen.

    2. wird eines seiner kinder beendet, so springt der vater prozess
      in die funktion, die ich mit signal und SIGCHLD angegeben hab
      (weil er vom kind das signal SIGCHLD gesendet bekommt)

    3. in dieser funktion wartet er mittels wait auf das ende des kind prozesses

    4. er wartet in der funktion auf genau *EIN* kind
      d.h. mein server bleibt parallel und wird auch nach dem ende
      eines kindes nicht auf *ALLE* von ihm erzeugten kinder warten
      (also der haupt prozess haengt nach dem signal SIGCHLD nicht
      im wait fest und wartet auf andere von ihm erzeugte kinder die aber noch
      "laufen")

    5. die anderen kinder bleiben davon unbeeinflusst
      sie wissen nicht, dass ein anderes kind beendet wurde

    ok. ich denke das war es erstmal fuers erste.
    danke fuer die hilfe.

    [ Dieser Beitrag wurde am 19.12.2002 um 21:18 Uhr von entelechie editiert. ]



    1. der haupt-prozess kann weiterhin mehrere kinder erzeugen.

    Ja, ich will doch mal hoffen.

    1. wird eines seiner kinder beendet, so springt der vater prozess
      in die funktion, die ich mit signal und SIGCHLD angegeben hab
      (weil er vom kind das signal SIGCHLD gesendet bekommt)

    Nicht vom Kind bekommt er das Signal gesendet, sondern direkt vom Kernel. Anonsten stimmt alles.

    1. in dieser funktion wartet er mittels wait auf das ende des kind prozesses

    Ja, schau dir mal die manpage zu wait() an.

    1. er wartet in der funktion auf genau *EIN* kind
      d.h. mein server bleibt parallel und wird auch nach dem ende
      eines kindes nicht auf *ALLE* von ihm erzeugten kinder warten
      (also der haupt prozess haengt nach dem signal SIGCHLD nicht
      im wait fest und wartet auf andere von ihm erzeugte kinder die aber noch
      "laufen")

    Dein Programm läuft normal, der Kernel blockt (d.h. in diesem Fall: hält) alle anderen SIGCHLDs auf, d.h. diese werden dann später abgearbeitet.

    1. die anderen kinder bleiben davon unbeeinflusst
      sie wissen nicht, dass ein anderes kind beendet wurde

    Sie wissen es nicht, aber wenn sich ein weiteres Kind terminiert, kann es sein, dass es ein bisschen warten muss. Das passiert aber _relativ_ selten.



  • Besser ist es wenn du einen Parentprocess erzeugst.
    Dadurch kann es nie passieren, daß du Zombies schaffst wenn der Parentprocess mal abstürtzen sollte.



  • @unix-tom:
    was meinst du mit parent prozess erzeugen?
    ich habe doch automatisch nach jedem fork einen
    parent und mehrere kind prozesse.

    odda wie?

    sorry bin da wohl noch nicht so ganz dahintergestiegen,
    ist mein erster versuch in paralleler programmierung.
    kannst du mir das genauer erklaeren was du meinst,
    oder eine gute seite empfehlen?
    (bitte keine antworten schau mal auf google.de oder so 🙄 )



  • FYI:

    in sachen fork() und exit() ist mir kürzlich auch dieser
    artikel untergekommen:

    Unix Programming FAQ:
    1.1.3 Why use _exit rather than exit in the child branch of a fork?

    http://www.faqs.org/faqs/unix-faq/programmer/faq/


Anmelden zum Antworten