user2373043
user2373043

Reputation: 21

multi-threading in C : do we need to set unused thread to NULL?

Here is the threaded-server code in C. My question is: do we need to set unused thread to NULL? In java, we need to set thread to NULL to let it return to thread pool.

I made the change to Martin Broadhurst's source code (see gray text as comment)

 /* 
 *  A threaded server
 *  by Martin Broadhurst (www.martinbroadhurst.com)
 *  Compile with -pthread
 */

#include <stdio.h>
#include <string.h> /* memset() */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>

#define PORT    "32001" /* Port to listen on */
#define BACKLOG     10  /* Passed to listen() */

void *handle(void *pnewsock)
{
    /* send(), recv(), close() */

    return NULL;
}

int main(void)
{
    int sock;
    pthread_t thread;
    struct addrinfo hints, *res;
    int reuseaddr = 1; /* True */

    /* Get the address info */
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
        perror("getaddrinfo");
        return 1;
    }

    /* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sock == -1) {
        perror("socket");
        return 1;
    }

    /* Enable the socket to reuse the address */
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
        perror("setsockopt");
        return 1;
    }

    /* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
        perror("bind");
        return 0;
    }

    freeaddrinfo(res);

    /* Listen */
    if (listen(sock, BACKLOG) == -1) {
        perror("listen");
        return 0;
    }

    /* Main loop */
    while (1) {             
        pthread_attr_t *attr;  //<===I added this
        size_t size = sizeof(struct sockaddr_in);
        struct sockaddr_in their_addr;
        int * ptr;   //<===I added this
        ptr = malloc(sizeof(int));       //<===I added this
        ptr = accept(sock, (struct sockaddr*)&their_addr, &size);
        if (newsock == -1) {
            perror("accept");
        }
        else {
               printf("Got a connection from %s on port %d\n",
                inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));  
                //I added the following "if" statement
                if (pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED) != 0){
                    fprintf(stderr, "Failed to set thread detached\n");
                }
                else {
                    //if (pthread_create(&thread, NULL, handle, &newsock) != 0) {
                    if (pthread_create(&thread, attr, handle, ptr) != 0 ) {
                        fprintf(stderr, "Failed to create thread\n");
                     }
                }

        }
    }

    close(sock);

    return 0;
}

==========-============== code is from here: http://martinbroadhurst.com/source/threaded-server.c.html

Upvotes: 0

Views: 676

Answers (3)

Random832
Random832

Reputation: 39060

No. Well, it's not 100% clear what Java construct it is you're thinking of (I bet there's a close method you can call instead of setting it to null and having the GC take care of it), but that's irrelevant because...

  1. pthread_t is an integer (maybe) type, not a pointer, so it can't be set to NULL.
  2. C is not garbage collected, so even if it were a pointer the thread would have no way of knowing or caring that you set it to null.
  3. POSIX threads does not use a thread pool. The pthread_create function actually creates a brand-new OS-level thread, and returning from the handler actually exits it. (Well, not really. It still hangs around until you call pthread_join, since you didn't create it as a detached thread.)

What you should do is create the threads as detached threads, since your code right now is leaking joinable threads.

Also, using &newsock as the argument is dangerous, since it gets destroyed and recreated in every iteration of the main loop. This is a race condition that probably never showed up in the author's testing because under light load the main thread would be waiting for the next accept to return while it is accessed on the worker thread, and on most systems the same space will be used over and over for the variable.

You can use malloc to create a place to store the socket fd in (which you will need to free at the end of your handler function), or, if your platform allows this (most do), just cast the value to a pointer then cast it back out in the handler function.

Upvotes: 3

Eric
Eric

Reputation: 24974

You have a pthread_t as thread id, there is no object, and it don't work in the way as java gc.

Thread terminate in 1 of following cases:

  • its start function return,
  • the thread call pthread_exit()
  • canceled by pthread_cancel()
  • any of threads in the process call exit(),
  • the main thread returns, in this case, all threads in the process will terminate immediately,

Upvotes: 0

David Schwartz
David Schwartz

Reputation: 182827

Since C doesn't have objects, there is no object that represents the thread and so nothing to set to NULL. A detached thread will go away when it terminates. An undetached thread will go away when it's joined.

Upvotes: 2

Related Questions