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
>
next prev parent 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).