public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
From: "vc" <vcotirlea1@hotmail.com>
To: <pthreads-win32@sources.redhat.com>
Subject: problem using pthread_cancel and pthread_mutex_lock
Date: Mon, 23 Feb 2004 17:43:00 -0000	[thread overview]
Message-ID: <BAY2-DAV45e2Qw4hVJb0003de2c@hotmail.com> (raw)

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

             reply	other threads:[~2004-02-23 17:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-23 17:43 vc [this message]
2004-03-01 16:27 ` vc
2004-03-04 23:13   ` Ross Johnson
2004-03-09 14:06     ` vc
2004-03-09 14:15     ` Brano Kemen
2004-03-09 15:09       ` Panagiotis E. Hadjidoukas
2004-03-09 15:42         ` Brano Kemen
2004-02-24  4:23 Simon Gerblich
2004-02-26 15:59 ` vc
2004-03-09 23:25 Simon Gerblich
2004-03-10  0:57 ` Will Bryant
2004-03-10 11:11 ` vc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BAY2-DAV45e2Qw4hVJb0003de2c@hotmail.com \
    --to=vcotirlea1@hotmail.com \
    --cc=pthreads-win32@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).