2

I have

    client_sock = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len);        
    if (pthread_create(&newthread , NULL, (void * ) accept_request, client_sock) != 0) {
            perror("pthread_create");
    }

That's just part of the entire script. Every time I try to compile it, I get warning: passing argument 4 of 'pthread_create' makes pointer from integer without a cast

Any idea why this is happening? Thanks in advance.

0

3 Answers 3

6

Argument 4 is client_sock, which is the argument that gets passed to accept_request. It is expected to be a pointer, but since it's just passed through to your function, it can be an integer without doing any harm. Just cast it to void* to remove the warning.

On the other hand, the third argument accept_request should be a function pointer accepting void* and returning void*. You shouldn't have to cast it to void*. It would be best to change the declaration of accept_request to match the specification.

void *accept_request( void *client_sock );
Sign up to request clarification or add additional context in comments.

Comments

4

I assume client_sock is defined as "int client_sock". In this case you should write the following:

if (pthread_create(&newthread , NULL, (void * ) accept_request, &client_sock) != 0) {

Then in accept_request (which, btw, should be a function taking a pointer) you will do like:

void *accept_request( void *client_sock_addr ) {
   int client_sock = *((int*) client_sock_addr);
}

Converting an int to an (void*) might not be portable (as data sizes of int and void* are not necessarily the same). Of course, it might work on your current compiler...

Thanks jiles for pointing this: Depending on the rest of the code, the value at that address might change (for example if you have a loop around the accept construct and 2 accepts arrive before one thread is created). The nicest way to do it is indeed allocate memory with malloc like

int *client_sock_addr=malloc(sizeof(int)); 
*client_sock_addr = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len);        
if (pthread_create(&newthread , NULL, (void * ) accept_request, client_sock_addr) != 0) {
        perror("pthread_create");
}

And then in the function do:

void *accept_request( void *param ) {
   int *client_sock_addr = (int*) client_sock_addr;
   int client_sock = *client_sock_addr;

   // Before exiting the thread
   free(client_sock_addr);
}

3 Comments

int client_sock = -1; I'm not sure why, but when I put &client_sock instead of client_sock, the entire socket stops working. Any ideas?
This change introduces a new problem. There is nothing that ensures that the pointer and the data it points to remain valid until the thread is done with it. Some ways to fix this: malloc the parameter block and free it in the thread, have the thread signal that it is done with the parameter and wait for that before invalidating it.
Usually it is best to group the parameters to the thread in a struct with the pthread_t object. When you join with the thread, you can dispose of the struct or reuse it or whatever.
0

This is simply because you are not respecting the signature of pthread_create:

int pthread_create(pthread_t *restrict thread,
              const pthread_attr_t *restrict attr,
              void *(*start_routine)(void*), void *restrict arg);

As you can see the third argument should be a function pointer so the correct cast would be to (void *(*)(void*)) and for client_sock which will be the argument to start_routine you have to take the address like that &client_sock

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.