Q:

Pass pointer to on-stack variable for new thread - is this code safe?

Consider the following code:
void* echo_data(void* client_socket) {
    // for the sake of argument - suppose there's a lot of code here before we copy the socket to local variable:
    int socket = *(int*)client_socket;
    // send back whatever is coming from client
    return (void*)0;
}

int main(int argc, char* argv[]) {
    int server_socket = establish_connection();

    while (1) {
        int incoming_client_socket = wait_for_connection(server_socket);
        fprintf(stdout, "new connection accepted...\n");

        pthread_t client_thread;
        pthread_create(&client_thread, NULL, echo_data, (void*)&incoming_client_socket);
    }
}

I know I am ignoring return codes here, but this code doesn't actually run (there's no establish_connection or wait_for_connection) and was put together to convey an idea, so for the sake of argument let's say all functions always succeed...
I do, however, wonder specifically about the implication of using local variable as argument for a newly created thread.
Consider the following scenario:  

wait_for_connection accepts new connection and returns incoming_client_socket.
incoming_client_socket is passed "by reference" to echo_data in a newly created thread, while it is currently stored on main()'s stuck.
Now suppose that it takes some time until echo_data copies the data pointed by client_socket, and in the meantime, the main thread accepts another connection, which will overrun the previous incoming_client_socket - the thread then copies wrong data.

Is that a real concern?
if not, how come?
If so, what's a safe way of doing that?

A:

Is that a real concern?

Yes. Its not a safe way of doing it.
You can pass the value directly instead of passing its address.
pthread_create(&client_thread, NULL, echo_data, (void*) incoming_client_socket);`

and the thread function should be like
void* echo_data(void* client_socket) {
  int socket = (int)client_socket;
  /* your code */
}

If you wish to pass more than one elements to the thread, then you could wrap it inside a structure, create a structure pointer for it, allocate memory and fill the values and pass the pointer to the threads.
struct X {
  int socket;
  /* other members here*/
};

and
  while (1) {
    int incoming_client_socket = wait_for_connection(server_socket);
    fprintf(stdout, "new connection accepted...\n");
    struct X *ptr = malloc (sizeof(struct X));
    ptr->socket = incoming_client_socket;
    /* other assignment here */

    pthread_create(&client_thread, NULL, echo_data, (void*)ptr);
  }

And your thread func should look like
void* echo_data(void* client_socket) {
  // for the sake of argument - suppose there's a lot of code here before we copy the socket to local variable:
  struct X *ptr = (struct X *)client_socket;
  // send back whatever is coming from client
  return (void*)0;
}

Don't forget to free the memory.

