This is the mail archive of the pthreads-win32@sources.redhat.com mailing list for the pthreas-win32 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

problem using pthread_cancel and pthread_mutex_lock


Hi all,

I am using the pthread library and I'm having a problem while using
pthread_cancel and pthread_mutex_lock.
Problem description:
I start 2 threads: thread1 and thread2.
thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs and
then it is doing
a pthread_cancel for the thread2, then is doing a
pthread_mutex_unlock(&mutex)
Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the mutex
is owned
by the thread1, and at this point the cancel is called.
Even if in the cleanup procedure of the thread2 I'm doing an
pthread_mutex_unlock or
not, next time when the thread1 is trying a pthread_mutex_lock(&mutex) it
will block
and never gets the mutex.
Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
function fails
(ret value is 1)

So, my question is: how can a thread cleanly cancel another thread which is
waiting in a 'pthread_mutex_lock' call, so that this mutex is available
again ?

Here is a sample program:
====================

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>

void cleanup_routine(void *arg);
void reader_function(void *arg);
void monitor(void *arg);
int global_counter=0;

pthread_mutex_t my_mutex;
int id[2];
pthread_t reader[2];
int cancel_mode;


int main(int argc, char *argv[])
{
   int my_args;
   int err = 0;
   cancel_mode = 1;

   printf("We'll try to cancel with mode ASYNCHRONOUS\n");

   id[0] = 1;
   id[1] = 2;
   pthread_mutex_init(&my_mutex, NULL);

   my_args = 1;
   pthread_create( &reader[0], NULL, (void*)&monitor, (void *) &my_args);
   Sleep(2000);
   my_args = 2;
   pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
&my_args);

   while(1) {
 Sleep(1000);
   }
}

void monitor (void *arg )
{
   int retval;

   printf("Monitor: Entering monitor routine\n\n");

   printf("Monitor: monitor is locking thread...\n");
   pthread_mutex_lock(&my_mutex);
   printf("Monitor: monitor is locking thread - okay\n");
   Sleep (5000);

   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
reader[1]);
   retval = pthread_cancel (reader[1]);
   printf("Monitor: kill returns %d\n", retval);

   printf("Monitor: monitor is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Monitor: monitor is unlocking thread - okay\n");

   printf("Monitor: monitor running\n");
   Sleep (3000);
   printf("Monitor: monitor is locking thread...\n");
   pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock! It
will hang here!
   printf("Monitor: monitor is locking thread - okay\n");

   Sleep(1000);
   printf("Monitor: monitor is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Monitor: monitor is unlocking thread - okay\n");
}


int args;

void reader_function (void *arg )
{
   int i=0;
   int id, state;
   int retval;

   pthread_cleanup_push(cleanup_routine, NULL);
   retval = pthread_detach (pthread_self());

   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
   printf("Thread: pthread_setcancelstate:   old state was %d\n", state);

   if (cancel_mode == 1) {
       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
   }

   id = *(int *) arg;
   printf("Thread: entered thread %d\n", id);
   printf("Thread: thread returns: 0x%x\n", (unsigned int) pthread_self());

   printf("Thread: testthread is locking thread...\n");
   pthread_mutex_lock(&my_mutex);
   printf("Thread: testthread is locking thread - okay\n");

   // HERE: it shouldn't come here as the thread will be canceled by the
monitor thread
   printf("Thread: testthread is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Thread: testthread is unlocking thread - okay\n");

   printf("Thread: reader_function finished\n");

   pthread_cleanup_pop(0);
}


void cleanup_routine(void *arg)
{
   int ret = 0;
   printf("ThreadCleanup: cleanup called\n");
   Sleep(5000);

   ret = pthread_mutex_unlock(&my_mutex);
   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
   printf("ThreadCleanup:waitThread_cleanup done\n");
}


The output looks like:
=================
We'll try to cancel with mode ASYNCHRONOUS
Monitor: Entering monitor routine

Monitor: monitor is locking thread...
Monitor: monitor is locking thread - okay
Thread: pthread_setcancelstate:   old state was 0
Thread: entered thread 2
Thread: thread returns: 0x312d80
Thread: testthread is locking thread...
Monitor: monitor kills pthread 0x312d80:
Monitor: kill returns 0
Monitor: monitor is unlocking thread...
ThreadCleanup: cleanup called
Monitor: monitor is unlocking thread - okay
Monitor: monitor running
Monitor: monitor is locking thread...
ThreadCleanup:Cleanup routine unlock ret = 1
ThreadCleanup:waitThread_cleanup done


So, from the output can be seen that the 1st thread (called monitor) will
never be able
to gain the mutex again.

Sorry for the long post,
Any help will be appreciated,
Thanks a lot,
Viv


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]