seth.g
seth.g

Reputation: 15

c - socket failing when passed through pthread_create

I have a server that accepts clients. I'm doing some multi-threading, and when I create a thread, I pass the socketfd as an argument. The accept fails because the sockFd it takes is zero. However I can't figure out why this would be the case. The sockfd is valid for the take_client function, and it has been set up correctly. I just included this section of my code because I'm certain the issue is here.

void* thread_func(void* pSockfd) {
    int sockFd;
    sockFd = *(int*)pSockfd;
    printf("sockFD = %d\n", sockFd); //returns zero
    struct sockaddr_in sockAddr;
    socklen_t sockAddrSize;

    sockAddrSize = sizeof(struct sockaddr_in);
    accept(sockFd, (struct sockaddr*) &sockAddr, &sockAddrSize);

return 0;
}

void take_client(int sock) { //when called, 'sock' is a valid number > 0
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
}

If anything stands out that might be an issue, I'd be really grateful to hear. Thanks!

Upvotes: 0

Views: 521

Answers (2)

OznOg
OznOg

Reputation: 4732

there is a race condition in you code, it may look ok "sometimes":

void take_client(int sock) { //sock live on stack here
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
    // you pass the stack address of sock to your thread
}

The address you pass must remain valid when thread is running, thus either you can afford that(it is kind of "global" somewhere), either you need to allocate a new buffer and pass it to the thread.

Sometime you will see code casting sock value to void* ( (void*)sock) and casting back the pointer to an int in the thread.

This may work, but I think allocating a new buffer is better for readability, and gives a clear ownership of who is responsible for this buffer (having a shared 'sock' between threads would need locking to be perfectly safe).

Moreover, usually, you end up with the need of passing many more info to the thread, thus already having a buffer ease the evolution of your code.

Upvotes: 3

H.cohen
H.cohen

Reputation: 517

check out the man page for socket return value: "On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set appropriately." So a zero return value is valid. unless I didn't understand the issue you have.

Upvotes: 0

Related Questions