Mail Archives: cygwin/2001/08/18/19:07:07
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 -