tags:

views:

48

answers:

3

I'm sure I'm missing something basic, but I'm writing a program that fork()s several child processes, each of which create several pthreads. It seems that the pthread_create call never works from a child process. Here is sample code to explain what I mean:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

// Listen for a request from user proc i
void *wait_for_req(void *cvoid) {
     int req;
     int read_ret;
     printf("new thread started\n");
     pthread_exit(NULL);
}

void spawn_read_threads(int proc_num, int n) {
    int i;
    printf("About to spawn %d read threads\n", n);
    for (i=0; i<n; i++) {
        pthread_t *t;
        printf("spawning new thread\n");
        int create_result = pthread_create(t, NULL, wait_for_req, NULL);
        printf("_create returned %d\n", create_result);
        pthread_join(*t, NULL);
    }
}


int main() {
    if (!fork())
        spawn_read_threads(0, 1);
}

The output of this program is

About to spawn 1 read threads
spawning new thread

But if I comment out if comment out if (!fork()):

About to spawn 1 read threads
spawning new thread
_create returned 0
new thread started

So why doesn't execution get through create_result in the first case?

And if this is useful:

rob@ubuntu:/mnt/hgfs/Virtual Machines$ uname -a
Linux ubuntu 2.6.32-24-generic #42-Ubuntu SMP Fri Aug 20 14:24:04 UTC 2010 i686 GNU/Linux
+3  A: 

I can see one immediate problem with your code: pthread_create takes the address of an existing pthread_t variable and stores the new thread ID in it. You're passing an uninitialized pointer instead. You need to do something like:

pthread_t tid;
int create_result = pthread_create(&tid, NULL, wait_for_req, NULL);

I'd say you were just lucky when it worked once, because your current code essentially causes undefined behaviour.

casablanca
That did it... I thought that way had been causing an error for some reason... well I knew it would be that simple, thanks!
Rob Lourens
But any idea why it only broke from a child process?
Rob Lourens
@Rob Lourens: Like I said, you just got lucky. It could have very well broken otherwise as well.
casablanca
A: 
pthread_t t;
printf("spawning new thread\n");
int create_result = pthread_create(&t, NULL, wait_for_req, NULL);
printf("_create returned %d\n", create_result);
pthread_join(t, NULL);
Keshan
+1  A: 

Besides the errors you found in your answer, you are not supposed to call pthread_* from within the forked process. After, fork() only async-signal safe functions should be used. You must exec() first, and then you may create some pthreads.

karunski