Ein paar fragen zu den leidigen threads



  • Ich habe einen ISDN-Server geschrieben, da ich nun telephonie implementieren möchte muss ich mit unabhängigen Programmteile arbeiten können. Ich hatte es mit fork probiert aber es funktioniert nicht wie es soll, da ja dann die Sockets von zwei unabhängigen programme benutzt werden gibts ein heilloses Durcheinander. Also, fork ist für mich (ausser zur initialen Gabelung um aus dem Programm ein Daemon zu machen) unbrauchbar.

    Heute, gut, gestern abend habe ich pthreads_create entdeckt, das Zeugs funktioniert wunderbar bis auf etwas das störend ist, sobald die "gethreadte" Funktion aufgerufen wird, erscheinen zwei isdnserver (so heisst das Programm, sehr originell, oder?) zusätzlich, sobald die aufgerufene Funktion sich beendet, wird eines dieser isdnserver beendet aber die andere (zweite) bleibt und will partout nicht verschwinden! Ich habe dann zwei isdnserver Einträge in z.B. "top". Beim beenden des isdnservers werden dann auch nich alle Funktionen die bei signal() definiert wurden.

    Hier ist der code:

    Zuerst den Teil der die Funktion aufruft

    ...
    ...
    if (command[1]!="" and command[2]!="")
       {
       stringstream out;
       out << command[1] << "-" << command[2] << "|" << i;
       char conv[30];
       strcpy(conv,out.str().c_str());
       char *arg=conv;
       thread_t list;
       if (pid=pthread_create(&list, NULL,testing,(void*)arg)!=0)
          {
          cout << "ERROR\n";
          }
       cout << "PID=" << list << "\n";                             
       }
    ...
    ...
    

    Und dann die Funktion selbst

    ...
    ...
    void *testing(void* ptr)
         {
         string buffer=(char *)ptr;
         map<int,string>exploded;
         exploded=explode("|",buffer); // explode(string,string) ist eine eigene Funktion
         callsList(exploded[0],atoi(exploded[1].c_str()));
         return 0;
         }
    ...
    ...
    

    callsList ist eine Funktion die an den client (den FileDescriptor des Sockets wird durch exploded[1] übermittelt) eine unter Umständen ellenlange Liste sendet.

    Ist das Verhalten dass, ich im zweiten Paragraphen geschildert habe normal? Oder, was mache ich falsch?

    vielen Dank im voraus.



  • Ich bin zwar kein POSIX-Threads-Experte, aber soweit ich weiß, sollte das Hauptprogramm, das den Thread erzeugt, irgendwann mit pthread_join() dessen Rückgabewert abholen, sonst bleibt ein "Rest" von dem Thread im Speicher hängen - und den siehst du dann in der Prozesstabelle.



  • Hi !

    pthread_join wartet doch soweit ich weiß bis ein Thread beendet ist, oder? Nen Rückgabewert kriegt man auch, aber die Hauptfunktion ist doch zu warten.

    Oder 😕



  • @Headhunter:
    Wird ein Thread beendet (mit pthread_exit()), so liefert pthread_join() einen Zeiger auf den Rückgabewert, d.h. der Wert selbst ist noch Bestandteil des Threads (kann man mit Ausgabe der Zeiger selbst leicht überprüfen) und bleibt "reserviert". Die man-Page von pthread_exit() sagt u.a.:

    [...], but application visible process resources, including, but not limited to, mutexes and file descriptors are not released.

    Was auch immer das genau heißen mag, irgendetwas bleibt wohl zurück, wenn man den Rückgabewert nicht "abholt".

    Die man-Page von pthread_join() sagt explizit:

    When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called once for each joinable thread created to avoid memory leaks.

    Das ist wohl eindeutig!



  • Hi Martin und Headhunter, erstmals vielen Dank für eure Anworten.

    Martin, pthread_join friert den "anrufeden" Teil ein bis der erzeugte Thread mit seiner Arbeit fertig ist, ich hab es ausprobiert, ausserdem löst er mein Problem nicht, der zweite isdnserver geistert auch dann in den Untiefen des Speichers herum. Es ist auch komisch, am Schein an kann ich z.B. 20 Listen gleichzeitig abfragen (was zu meiner Freude, sehr schnell abgearbeitet wird) und die neu erzeugten 20 "isdnserver" werden auch beendet und gelöscht oder sie werden zumindest in top nicht mehr angezeigt.

    Also, pthread_join kann nicht die Lösung sein, erstens friert es das ganze ein bis auf den ausführenden Thread ein, so kann ich ja den Server lassen wie er ist und zweitens verschindet der böse Zwilling von isdnserver auch so nicht. Es muss irgend etwas anderes sein.

    Grüsse



  • Mit diesem Testprogramm passiert genau dasselbe, es werden drei angebliche Kopien des Programms erzeugt und wenn die "gethreadte" Funktion fertig ist, wird eine gelöscht, zwei bleiben aber. Scheint das normale Vorgehen zu sen.

    Aber wie schliesse ich alles richtig (Sockets z.B.) wenn ich das Prgramm (in Referenz zu isdnserver) beende? Die PID die von (in dem nachfolgenden Beispiel) mythread gespeichert wird stimmt mit der tatsächlichen PID nicht überein.

    #include <pthread.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    void *thread_function(void *arg) {
      int i;
      for ( i=0; i<20; i++ ) {
        printf("Thread says hi!\n");
        sleep(1);
      }
      return NULL;
    }
    
    int main(void) {
    
      pthread_t mythread;
    
      if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
        printf("error creating thread.");
        abort();
      }
    
      if ( pthread_join ( mythread, NULL ) ) {
        printf("error joining thread.");
        abort();
      }
    
      sleep(60);
    
      exit(0);
    
    }
    


  • Ich hab' es herausgefunden, das mit dem zweiten thread is normal, gut, normal hängt von der Kernel Version ab, ab 2.4.19 sollte der zweite thread nicht mehr erscheinen.

    Dieser thread ist am schein an so ein "managing thread" der automatisch erzeugt wird.

    Gruss


Anmelden zum Antworten