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

Hi all,

I found a solution to the problem I have described (see below my orig email)
and I'm wondering if this is ok ...

In my program I have to use asynchronous cancellation as I have something
called a "thread monitor" and
if one thread hangs I want after a while my thread monitor to kill it
regardless of where that
thread hanged. Using asynchronous cancellation makes problems (as I
discovered until now)
only when a thread is in a pthread_mutex_lock call, as in that case, by
canceling the thread
the mutex is in an unusable state.

So what I have done is like this (see below): just before calling the
pthread_mutex_lock
I change the cancellation to deferred cancellation then call the
pthread_mutex_lock and then set back
the original cancellation mode:

void reader_function (void *arg )
{

 pthread_cleanup_push(cleanup_routine, (void *) &test_data);

 retval = pthread_detach (pthread_self());

 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);

 retval = protect_code_with_mutex_deferred();
 pthread_cleanup_pop(1);

 pthread_exit(NULL);
}

int protect_code_with_mutex_deferred(void)
{
 int oldtype = 0;

 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
 retval = pthread_mutex_lock(&my_mutex);
 pthread_setcanceltype(oldtype, NULL); //put back
 [...]
}

This seems to work just fine and seems to solve my problem. As I'm generaly
using asynchronous cancellation
my thread can be killed at any point and when a pthread_mutex_lock is done
because I switch
to deferred cancellation I can be sure that my thread will first go out from
the pthread_mutex_lock
call and then it will be canceled, so in my cleanup fction I can do an
unlock of the mutex.

But I am wondering why this way of solving the problem was not added to the
pthread library? Am I missing something?
Is something wrong here? Am I overseen something?

If no, then in the pthread library in the pthread_mutex_lock at the
beginning the:
 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be called
and at the end the:
 pthread_setcanceltype(oldtype, NULL);
could be called.
Of course some other changes are needed as pthread_setcanceltype calls also
pthread_mutex_lock, but for internal use, I mean within the library the
pthread_mutex_lock
could be used with one more param, so that when pthread_mutex_lock is called
from within the lib these
2 lines will never be executed.

Any feedback would be appreciated.
Thanks a lot,
Viv


----- Original Message -----
From: "vc" <vcotirlea1@hotmail.com>
To: <pthreads-win32@sources.redhat.com>
Sent: Monday, February 23, 2004 6:45 PM
Subject: 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
>

  reply	other threads:[~2004-03-01 16:27 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-23 17:43 vc
2004-03-01 16:27 ` vc [this message]
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-DAV61fMHTs2FZQ000129c8@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).