Web lists-archives.com

problem with mmap and fork()




Hello everyone,

I have a program (attached) that works correctly on my mac but does
not work with Cygwin on Windows 10. I'm running the latest version of
Cygwin (downloaded the updates two days ago) and using gcc as the c
compiler.

What happens in the buggy execution is that the child obtains a lock
before the parent releases it. I'm using mmap and a pthread_mutex_t
object along with fork(). Again, this exact code works correctly on my
Mac running Mojave.

I've looked at the archives and online and I can't find any hints as
to what I may be doing incorrectly here

Thanks.
// smtest2.c
//
// Dr. Glyn Gowing
// LeTourneau University
// COSC 4653 - Advanced Networks
//
// This program demonstrates how to use a lock with fork()ed processes by using
// shared memory.

#include <stdio.h>         // needed for printf
#include <sys/mman.h>      // needed for mmap
#include <unistd.h>        // needed for fork
#include <pthread.h>       // needed for the mutex and the mutexattr structs and functions


// this create_shared_memory function was found on stack exchange.
void* create_shared_memory(size_t size) 
{
   // Our memory buffer will be readable and writable:
   int protection = PROT_READ | PROT_WRITE;
   
   // The buffer will be shared (meaning other processes can access it), but
   // anonymous (meaning third-party processes cannot obtain an address for it),
   // so only this process and its children will be able to use it:
   int visibility = MAP_ANONYMOUS | MAP_SHARED;
   
   // The remaining parameters to `mmap()` are not important for this use case,
   // but the manpage for `mmap` explains their purpose.
   return mmap(NULL, size, protection, visibility, 0, 0);
}
// end borrowed code


int main() 
{
   // create mutex and mutexattr structs so we can create the mutex
   // these are created as shared memory so they can be accessed by both processes
   pthread_mutex_t *lock = (pthread_mutex_t *)create_shared_memory(sizeof(pthread_mutex_t));
   pthread_mutexattr_t *attr = (pthread_mutexattr_t *)create_shared_memory(sizeof(pthread_mutexattr_t));
   
   // initialize the mutexattr struct
   pthread_mutexattr_init(attr);
   // set it so it can be shared between processes
   // without this, the child will not be able to acquire the lock even if it is
   // in shared memory.
   pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);

   // initialize the mutex itself, using the attributes we just created
   pthread_mutex_init(lock, attr);
  
   // fork()
   int pid = fork();

   if (pid == 0)  // child
   {
      printf("Child sleeping 5\n");
      // sleep 5 seconds to give parent a chance to acquire lock
      sleep(5);
      // try to acquire lock. This will block until lock is acquired
      pthread_mutex_lock(lock);
      printf("child: acquired lock - Sleeping 3 seconds\n");
      sleep(3);
      // release lock after acquiring it
      pthread_mutex_unlock(lock);
      printf("child: unlocked.\n");
   } 
   else  // parent
   {
      // acquire lock immediately to force child to block
      pthread_mutex_lock(lock);
      printf("parent: acquired lock - Sleeping 10 seconds\n");
      sleep(10);
      // release lock to give child a chance
      pthread_mutex_unlock(lock);
      printf("parent: unlocked. Sleeping 5 to let child catch up.\n");
      sleep(5);
   }
   
   // mmap'ed memory is automatically unmapped when the process ends.
   return 0;
}
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple