I'm perhaps not very polite asking on this list without
waiting the usual lurking time, but I've been googling
this problem for a while yesterday and I did not find out
anything about it. Still the problem is very clear:

I wrote a sort of 'hello world' program where a global
mutex is created to synchronize access to a resource
shared between a parent and a child process created with a
Unix 'fork' call.

The child *should* gain the lock first, as the parent is given
a 2 seconds wait before attempting to lock the mutex. Then
it should release the lock giving way to the parent. That's all.
Simply the calls to apr_global_mutex_[lock|trylock|unlock]
wait forever and never return.

I also thought the apr_global_mutex_create returned an implicitly
locked mutex and tried to unlock it. Also this call would block
forever. Where did I get it wrong?

I asked also other people who are using global mutexes in
their projects and they observed the same problem when they
run my program and could not give an explanation.

The program is so simple that I dare attach it here. It is
a way to become familiar with tools that I hope will be used to
design and implement a new software component to be developed
for Apache Rivet, if this can work as an excuse for my
intrusiveness.

thanks for any help.

 -- Massimo Manghi





/*
 * Concurrency of parent and child processes using apr_global_mutex_*
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <apr-1.0/apr_pools.h>
#include <apr-1.0/apr_global_mutex.h>

#define MUTEX_NAME      "MUTEX"

int main(int argc,char** argv)
{
    apr_status_t apr_s;
    apr_pool_t*	 aPool;
    apr_global_mutex_t* mutex_s = NULL;
    pid_t   cpid;

    apr_s = apr_pool_initialize();
    apr_s = apr_pool_create (&aPool,NULL);
    if (apr_s != APR_SUCCESS)
    {
	    fprintf (stderr,"....could not initialize the pool...\n");
	    exit(1);
    }

    /* now, we create a global mutex */

    apr_s = apr_global_mutex_create (&mutex_s,MUTEX_NAME,APR_LOCK_DEFAULT,aPool);
    if (apr_s != APR_SUCCESS)
    {
        fprintf(stderr,"damn....could not create the mutex\n");
        exit(1);
    }
    fprintf (stderr,"[p] mutex created\n");

    apr_s = apr_global_mutex_child_init(&mutex_s,MUTEX_NAME,aPool);
    if (apr_s != APR_SUCCESS)
    {
	fprintf (stderr,"[p] gasp...could not map the mutex...bye\n");
	exit(1);
    }
    fprintf (stderr,"[p] acquired map to mutex type '%s'\n",apr_global_mutex_name(mutex_s));

    /* Parent and child fork here. The child will be given more chances to gain access to
     the protected resource as first */

    cpid=fork();
    if (cpid == 0)
    {
        apr_s = apr_global_mutex_child_init(&mutex_s,MUTEX_NAME,aPool);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[c] gasp...could not map the mutex...bye\n");
            exit(1);
        }
        fprintf (stderr,"[c] acquired map to mutex type '%s'\n",apr_global_mutex_name(mutex_s));
        fprintf (stderr,"[c] child proc attempting to lock the mutex...\n");
        apr_s = apr_global_mutex_lock(mutex_s);
        if (apr_s == APR_SUCCESS)
        {
            fprintf (stderr,"[c] fallito\n");
            exit(1);
        }
        fprintf (stderr,"[c] ok, child got the lock!\n");

	/* whatever the resource we protect with the mutex the child
	   process can manipulate it here */

	sleep(2);

        apr_s = apr_global_mutex_unlock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[c] mhhh....unlock fails...why?\n");
            exit(1);
        }
        fprintf (stderr,"[c] unlocked\n");
    }
    else
    {
	/* we give che child process a fair advantage to gain the lock on the mutex */

	sleep(2);

        fprintf(stderr,"[p] parent process attempts to lock the mutex...\n");
        apr_s = apr_global_mutex_lock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"failed\n");
            exit(1);
        }
        fprintf (stderr,"[p] ok, parent got the lock!\n");

	/* it's the parent turn to access and manipulate the protected
	   resource */

        apr_s = apr_global_mutex_unlock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[p] mhhh....unlock fails...why?\n");
            exit(1);
        }
        fprintf (stderr,"[p] mutex unlocked\n");

    }

    fprintf (stderr,"cpid: %d comes here...\n",cpid);

    exit(0);
}

Reply via email to