From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31577 invoked by alias); 1 Mar 2004 16:27:53 -0000 Mailing-List: contact pthreads-win32-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: pthreads-win32-owner@sources.redhat.com Received: (qmail 31560 invoked from network); 1 Mar 2004 16:27:48 -0000 Received: from unknown (HELO hotmail.com) (65.54.246.196) by sources.redhat.com with SMTP; 1 Mar 2004 16:27:48 -0000 Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; Mon, 1 Mar 2004 08:27:47 -0800 Received: from 62.245.182.10 by bay2-dav61.bay2.hotmail.com with DAV; Mon, 01 Mar 2004 16:27:47 +0000 X-Originating-IP: [62.245.182.10] X-Originating-Email: [vcotirlea1@hotmail.com] X-Sender: vcotirlea1@hotmail.com From: "vc" To: References: Subject: Re: problem using pthread_cancel and pthread_mutex_lock Date: Mon, 01 Mar 2004 16:27:00 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-ID: X-OriginalArrivalTime: 01 Mar 2004 16:27:47.0848 (UTC) FILETIME=[221EE880:01C3FFAA] X-SW-Source: 2004/txt/msg00019.txt.bz2 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" To: 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 > #include > #include > #include > #include > > 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 >