tags:

views:

42

answers:

3

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.

+5  A: 

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 );
Potatoswatter
+2  A: 

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);
}
vladmihaisima
Tech163
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.
jilles
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.
Potatoswatter
A: 

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

Jens Gustedt