Santhosh N
Santhosh N

Reputation: 157

mmap() for shared memory and threads

I am having the following C function:

int ipc_test(char *tstr)
{
    int *x = mmap(0, 4, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

    if(fork() == 0) {
        *x = getpid();
        exit(0);
    } else {
        int status;
        printf("%s: Child %d exited.\n", tstr, wait(&status));

        printf("%s: Child pid from mmap: %d\n", tstr, *x);
    }
}

I am calling the above as below:

void *thread_func(void *data)
{
    int i=0;

    while(i<3) {
        ipc_test(data);
        i++;
        printf("\n");
    }
}

int main(int ac, char **av)
{
    pthread_t th1, th2, th3;

    pthread_create(&th1, NULL, thread_func, "thread1");
    pthread_create(&th2, NULL, thread_func, "thread2");
    pthread_create(&th3, NULL, thread_func, "thread3");

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    pthread_join(th3, NULL);
}

Output:

thread3: Child 13248 exited.
thread3: Child pid from mmap: 13248

thread2: Child 13249 exited.
thread2: Child pid from mmap: 13249

thread3: Child 13250 exited.
thread3: Child pid from mmap: 0

thread3: Child 13252 exited.
thread3: Child pid from mmap: 0

thread1: Child 13251 exited.
thread1: Child pid from mmap: 13250

thread1: Child 13253 exited.
thread1: Child pid from mmap: 0

thread1: Child 13254 exited.
thread1: Child pid from mmap: 0

thread2: Child 13255 exited.
thread2: Child pid from mmap: 13252

thread2: Child 13256 exited.
thread2: Child pid from mmap: 13256

It can be noticed that there are mismatches in the pid values printed. If I guard the code in ipc_test with a mutex, the pid values get printed properly. Is the way the mmap function is used above not thread safe?

Upvotes: 2

Views: 2100

Answers (1)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215193

While there may be other problems in your program, the most obvious problem is that you're using wait to wait for a child process to exit when there may be more than one. This will end up randomly "stealing" the child process from another thread rather than waiting for the one you wanted to wait for (the one you just created in this thread). You need to use waitpid and request the specific child process you just created (which requires saving the return value of fork rather than throwing it away). In general, use of wait is essentially always a bug except in toy/sample programs. Always use waitpid with the explicit pid you want to wait for.

Upvotes: 2

Related Questions