Question

I have the following code that initializes a shared memory containing 1 mutex and 1 condition variable then forks a process where the parent passes to the child some characters through a pipe and signals the child to go an read it.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>



#ifndef _POSIX_THREAD_PROCESS_SHARED
#error This system does not support process shared mutex
#endif

pthread_cond_t *cvptr;    //Condition Variable Pointer
pthread_condattr_t cattr; //Condition Variable Attribute
pthread_mutex_t    *mptr; //Mutex Pointer
pthread_mutexattr_t matr; //Mutex Attribute

int   shared_mem_id;      //shared memory Id
int   *mp_shared_mem_ptr; //shared memory ptr -- pointing to mutex
int   *cv_shared_mem_ptr; //shared memory ptr -- pointing to condition variable

/* Read characters from the pipe and echo them to stdout. */
void read_from_pipe (int file)
{
    printf("read_from_pipe()\n");

    FILE *stream;
    int c;
    stream = fdopen (file, "r");

    // Lock mutex and then wait for signal to relase mutex
    printf("child mutex lock \n");
    pthread_mutex_lock( mptr );
    printf("child mutex locked\n");

    printf("child wait\n");
    pthread_cond_wait( cvptr, mptr );
    printf("child condition woke up\n");

    while ((c = fgetc (stream)) != EOF) 
        putchar (c);
    fclose (stream);

    printf("child mutex unlock\n");
    pthread_mutex_unlock( mptr );
}

/* Write some random text to the pipe. */
void write_to_pipe (int file)
{
    printf("write_to_pipe()\n");

    FILE *stream;
    stream = fdopen (file, "w");
    fprintf (stream, "hello, world!\n");
    fprintf (stream, "goodbye, world!\n");
    fclose (stream);

    pthread_cond_signal( cvptr );
}

int main (void)
{

    int  rtn;
    size_t shm_size;

    /* initialize shared memory segment */
    shm_size = 1*sizeof(pthread_mutex_t) + 1*sizeof(pthread_cond_t);

    if ((shared_mem_id = shmget(IPC_PRIVATE, shm_size, 0660)) < 0)
    {
        perror("shmget"), exit(1) ;
    }
    if ((mp_shared_mem_ptr = (int *)shmat(shared_mem_id, (void *)0, 0)) == NULL)
    {
        perror("shmat"), exit(1);
    }

    //Offset to find the location of the condition variable in the shared memory
    unsigned char* byte_ptr = reinterpret_cast<unsigned char*>(mp_shared_mem_ptr);
    byte_ptr += 1*sizeof(pthread_mutex_t);

    mptr = (pthread_mutex_t *)mp_shared_mem_ptr;
    cvptr = (pthread_cond_t *)byte_ptr;

    // Setup Mutex
    if (rtn = pthread_mutexattr_init(&matr)) 
    {
        fprintf(stderr,"pthreas_mutexattr_init: %s",strerror(rtn)),exit(1);
    }
    if (rtn = pthread_mutexattr_setpshared(&matr,PTHREAD_PROCESS_SHARED))
    {
        fprintf(stderr,"pthread_mutexattr_setpshared %s",strerror(rtn)),exit(1);
    }
    if (rtn = pthread_mutex_init(mptr, &matr))
    {
        fprintf(stderr,"pthread_mutex_init %s",strerror(rtn)), exit(1);
    }

    //Setup Condition Variable
    if(rtn = pthread_condattr_init(&cattr))
    {
        fprintf(stderr,"pthread_condattr_init: %s",strerror(rtn)),exit(1);
    }
    if(pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))
    {
        fprintf(stderr,"pthread_condattr_setpshared %s",strerror(rtn)),exit(1);
    }
    if(pthread_cond_init(cvptr, &cattr))
    {
        fprintf(stderr,"pthread_cond_init %s",strerror(rtn)),exit(1);
    }

    pid_t pid;
    int mypipe[2];

    /* Create the pipe. */
    if (pipe (mypipe))
    {
        fprintf (stderr, "Pipe failed.\n");
        return EXIT_FAILURE;
    }

    /* Create the child process. */
    pid = fork ();
    if (pid == (pid_t) 0)
    {
        printf ("Child Forked!.\n");

        /* This is the child process.
        Close other end first. */
        close (mypipe[1]);
        read_from_pipe (mypipe[0]);
        return EXIT_SUCCESS;
    }

    else if (pid < (pid_t) 0)
    {
        /* The fork failed. */
        fprintf (stderr, "Fork failed.\n");
        return EXIT_FAILURE;
    }
    else
    {
        printf ("Parent Forked!.\n");

        /* This is the parent process.
        Close other end first. */
        close (mypipe[0]);
        write_to_pipe (mypipe[1]);
        return EXIT_SUCCESS;
    } 
}

I think I did something wrong with the initialization of the variables, the code does not core dump but somehow only prints:

Parent Forked!.
write_to_pipe()

Any ideas?

Was it helpful?

Solution

It's possible that write_to_pipe is signalling the condition variable before read_from_pipe reaches the pthread_cond_wait. Condition variables don't do any kind of buffering or counting of signals, so it will simply be lost.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top