delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2001/08/18/19:07:07

Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT sources DOT redhat DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT sources DOT redhat DOT com>
List-Help: <mailto:cygwin-help AT sources DOT redhat DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT sources DOT redhat DOT com
Delivered-To: mailing list cygwin AT sources DOT redhat DOT com
From: David Lum <dlum AT alum DOT mit DOT edu>
MIME-Version: 1.0
Message-ID: <15230.62731.676056.47490@wallaroo.lum.org>
Date: Sat, 18 Aug 2001 18:06:51 -0500
To: cygwin AT cygwin DOT com
Subject: bug in pthread_mutex_init (cygwin-src-20010813)
X-Mailer: VM 6.89 under 21.1 (patch 14) "Cuyahoga Valley" XEmacs Lucid

Hi.

I think there's a problem with pthread_mutex_init in Cygwin-- I looked
at the source code (from 8/13/01) and it verified my suspicions.

The implementation of pthread_mutex_init in "winsup/cygwin/thread.cc"
does this:

> int
> __pthread_mutex_init (pthread_mutex_t *mutex,
>                       const pthread_mutexattr_t *attr)
> {
>   if ((((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE))
>     // a pshared mutex
>     return EBUSY;
>   ...
> }

This is bogus!  The pthread specification permits the passed-in mutex
pointer to refer to completely uninitialized memory.  However, the
first line of code here accesses a flag from that region of random
memory.  If the bit happens to be zero, all is well.  But if it
happens to be 1 then the call fails with EBUSY.

Below I've attached (inline) a simple test program to demonstrate this
bug.  All it does is make a bunch of calls to pthread_mutex_init,
simulating the effect of starting with random, uninitialized memory.
Typical output for me looks like this:

   GIRAFFE:/f/lum/cygwin> ./mutex.exe
   Mutex contains: 0x58 0x0 0x0 0x0
     --> OK.

   Mutex contains: 0xaf 0x80 0x96 0x8d
     --> Failed to initialize a mutex: 16 = Device or resource busy

It fails on the second call with the expected EBUSY return code.

I don't really have any suggestions on how to fix this, since it was
probably caused by the introduction of "pshared" mutexes (which I do
not understand).  But I'll bet someone on the list does.

				       -Dave

-- 
 David Lum                              713-868-6950 (Houston)
 dlum AT alum DOT mit DOT edu                      703-318-1266 (Dulles)

/*------------------------------------------------------------------------------
 *
 * Sample program to demonstrate a mutex bug in Cygwin 8/13/01
 *
 *----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>

static void randomizeMutexBits( pthread_mutex_t*);
static void showMutexBits( pthread_mutex_t*);

int
main(			char**			argv,
			char			argc)
{
   pthread_mutex_t	mut;
   int			retval;

   while( 1) {
      /*
       * If the following line is uncommented, all goes well.
       * However, that's not part of the pthread contract!  You're
       * supposed to be able to pass in uninitialized memory to
       * the pthread_mutex_init function.
       */
      /* memset( &mut, 0, sizeof( pthread_mutex_t)); */

      /*
       * Print out the contents of the mutex for debugging.
       */
      showMutexBits( &mut);

      /*
       * Try to initialize the mutex.
       */
      if( (retval = pthread_mutex_init( &mut, NULL)) != 0) {
	 printf( "  --> Failed to initialize a mutex: %d = %s\n", retval,
		 strerror( retval));
	 exit( -1);
      } else {
	 printf( "  --> OK.\n\n");
	 pthread_mutex_destroy( &mut);
      }

      /*
       * For the next time through the loop, simulate the random bits
       * found in uninitialized memory.
       */
      randomizeMutexBits( &mut);
   }

   exit( 0);
}

static void
randomizeMutexBits(	pthread_mutex_t*	mutex)
{
   unsigned char*	uc;
   int			i;

   uc = (unsigned char*) mutex;
   for( i=0; i<sizeof( *mutex); i++) {
      uc[i] = (unsigned char) (255.0*rand()/(RAND_MAX+1.0));
   }
}

static void
showMutexBits(		pthread_mutex_t*	mutex)
{
   unsigned char*	uc;
   int			i;

   printf( "Mutex contains: ");
   uc = (unsigned char*) mutex;
   for( i=0; i<sizeof( *mutex); i++) {
      printf( "0x%x ", uc[i]);
   }
   printf( "\n");
}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019