PThread Problem



  • Hallo,

    ich habe angefangen mit pthread's zu arbeiten, habe aber nun ein kleines Problem. Mein kleines Beispielprogramm stoppt einfach. Der KDE System Guard zeigt mir zudem eine sehr große VmSize.
    Der Speicher wird vollgestopft. Was mache ich falsch bzw. was habe ich vergessen?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
    
    pthread_mutex_t MUTEX;
    
    void *threadfunc(void *ptr);
    
    void *threadfunc(void *ptr) {
        pthread_mutex_lock(&MUTEX);
        printf("Thread CREATED\n\n");
        pthread_t id;
        pthread_create(&id, NULL, &threadfunc, NULL);
    
        int i = 0;
        for(i; i <= 10; i++) {
            printf(" %i ", i);
            //sleep (1);
        }
        pthread_mutex_unlock(&MUTEX);
    }
    
    int main(void) {
    
        pthread_t id;
        pthread_mutex_init(&MUTEX, NULL);
        pthread_create(&id, NULL, &threadfunc, NULL);
    
        while(1);
    
        return 0;
    }
    

    mfg

    Robert



  • Dein Beispielprogramm hat in main() ja auch eine Endlosschleife. Der Thread wird vermutlich gestartet, durchlaufen, beendet und das Hauptprogramm verbrät derweil CPU-Zeit soviel es bekommen kann.

    Was wolltest Du denn erreichen? Evtl. mit pthread_join auf den Thread warten?



  • hmm naja die Anmerking mit dem while(1); is richtig, aber mein Problem besteht eher darin, dass die Threadfunktion wieder einen Thread erstellen soll (welcher genau die selbe funktion beinhaltet) und das wird bis zu einem gewissen Zeitpunkt gemacht nur dann werdn plötzlich keine threads mehr erstellt und der Speicher scheint voll zu sein. Ich verstehe nicht was ich an Speicher wider freigeben muss. Die Threads beenden sich doch ... und ein neuer thread wird nur erstellt wenn der MUTEX wieder freigeschalten ist.

    Ist bestimmt ein Denkfehler, aber ich erkenne Ihn nicht 😞

    Um die ganze Zeit Threads erstellen zu können, darf main() einfach nicht verlassen werden (deswegen while(1); )



  • Du musst die neu erzeugten Threads entweder mit pthread_detach "loslösen" oder irgendwann mit pthread_join wieder mit einem Elternthread zusammenführen. Sonst bleibt jeder Thread auch nach dem Durchlaufen im Speicher, weil das System darauf wartet, dass jemand den Returnwert abholt.

    Ich empfehle nach dem pthread_create ein pthread_detach auf die id.



  • danke genau das wars was ich gesucht habe. 🙂



  • dumme frage:
    du weißt schon, dass du rekursiv immer mehr threads erzeugst, oder?



  • ja weiß ich ... ist auch so gewollt. der thread soll sich immer wieder selbst erzeugen um über einen socket zu empfangen und entsprechend darauf zu reagieren was er empfangen hat.

    Mit pthread_detach(id) löse ich den neu erzeugt von alten ab. der alte beendet sich und das wars. funktioniert auch ganz gut ... bin natürlich offen für bessere Vorschläge

    Robert



  • rona schrieb:

    der thread soll sich immer wieder selbst erzeugen um über einen socket zu empfangen und entsprechend darauf zu reagieren was er empfangen hat.
    ...
    bin natürlich offen für bessere Vorschläge

    wie wär's mit einer schleife um den socket herum? zeig mal bitte den code mit dem socket.



  • ... wieso ist eine schleife wirklich besser?

    struct _client_socket {
            int sock;
            struct sockaddr_in rfb_eric_server;
    };
    
    typedef struct _client_socket client_socket;
    
    int main(int argc, char *argv[]) {
    
        sock = (client_socket*) malloc(sizeof(client_socket));
        char buffer[BUFFSIZE];
        unsigned int len;
        int received = 0;
        int bytes = 0;
    
        pthread_mutex_init(&MUTEX, NULL);
    
        if (argc != 2) {
            fprintf(stderr, "USAGE: <server_ip> \n");
            exit(1);
        }
    
        /* Create the TCP socket */
        if ((sock->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            printf("Error creating Socket\n");
            return -1;
        }
    
        /* Construct the server sockaddr_in structure */
        //memset(sock->rfb_eric_server, 0, sizeof(struct sockaddr_in));       /* Clear struct */
        sock->rfb_eric_server.sin_family = AF_INET;                  /* Internet/IP */
        sock->rfb_eric_server.sin_addr.s_addr = inet_addr(argv[1]);  /* IP address */
        sock->rfb_eric_server.sin_port = htons(atoi("443"));       /* server port */
    
        /* Establish connection */
        if (connect(sock->sock, (struct sockaddr *)&sock->rfb_eric_server, sizeof(sock->rfb_eric_server)) < 0) {
            printf("Error Connecting\n");
            return -2;
        }
    
        /* Send the word to the server */
        len = strlen("e-RIC AUTH=");
        if (send(sock->sock, "e-RIC AUTH=", len, 0) != len) {
            printf("Error Sending\n");
            return -3;
        }
    
        /* creat thread reading messages from rfb-server */
        pthread_t reading_thread;
        pthread_create(&reading_thread, NULL, &read_PDUs, NULL);
        pthread_detach(reading_thread);
    
        while(1) {
            char retval = getchar();
    
            if (retval == 'f') {
                printf("Returned %i \n", send_xxx());
            }
    
            if (retval == 'q') {
                /* send_QuitMsg(local_sock); //-> only server-side */
                break;
            }
        }
    
        close(sock->sock);
        exit(0);
    }
    
    /* main receive-Thread */
    void * read_PDUs(void *ptr) {
    
        pthread_mutex_lock(&MUTEX);
    
        pthread_t again;
        pthread_create(&again, NULL, &read_PDUs, NULL);
        pthread_detach(again);
    
        u_int8_t *buffer = malloc(BUFFSIZE*sizeof(u_int8_t));
        int bytes = 1;
        int received = 0;
    
        printf("###########################\n");
    
        if ((bytes = recv(sock->sock, buffer, BUFFSIZE-1, 0)) < 1) {
            printf("Failed to receive bytes from server\n");
            exit(0);
        }
    
    // message handling
    
        free(buffer);
        pthread_mutex_unlock(&MUTEX);
    
    }
    


  • es gibt keinen grund für einen neuen thread. es gibt nicht mal einen grund, überhaupt threads zu verwenden. dein programm läuft so ab:

    verbinden -> was verschicken -> was empfangen -> was tun -> [zurück zu "was empfangen"]

    das schreit ja direkt nach einer schleife ab "was empfangen" :-). eine schleife verbraucht keinerlei ressourcen. wenn du threads erzeugst, werden damit immer ressourcen verbraucht - auch wenn du pthread_detach aufrufst.


Anmelden zum Antworten