From owner-freebsd-hackers Fri Nov 30 13:57:35 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from mx2.magma.ca (mx2.magma.ca [206.191.0.250]) by hub.freebsd.org (Postfix) with ESMTP id 4AF3F37B417; Fri, 30 Nov 2001 13:57:22 -0800 (PST) Received: from mail5.magma.ca (mail5.magma.ca [206.191.0.225]) by mx2.magma.ca (Magma's Mail Server) with ESMTP id fAULvMd2015435; Fri, 30 Nov 2001 16:57:22 -0500 (EST) Received: from durandal (mothership.macadamian.com [206.191.21.204]) by mail5.magma.ca (Magma's Mail Server) with SMTP id fAULvKTM024843; Fri, 30 Nov 2001 16:57:20 -0500 (EST) Message-ID: <094601c179ea$7cca85c0$2964a8c0@MACADAMIAN.com> From: "Louis-Philippe Gagnon" To: , Subject: Possible libc_r pthread bug Date: Fri, 30 Nov 2001 17:00:56 -0500 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.50.4133.2400 X-Mimeole: Produced By Microsoft MimeOLE V5.50.4133.2400 Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG If at first you don't succeed... I've encountered a problem using pthread_cancel, pthread_join and pthread_setcanceltype, I'm hoping someone can shed some light. (in a nutshell : pthread_setcanceltype doesn't seem to work in FreeBSD 4.4) (posted to -current and -hackers; if there's a more appropriate mailing list for this, please let me know) I recently encountered a situation where, after calling pthread_cancel to cancel a thread, the call to pthread_join hangs indefinitely. I quickly figured out that it was because the thread being cancelled was never reaching a cancellation point (in fact it was an infinite loop with no function calls at all). Sure enough, adding a pthread_testcancel() in the loop allowed pthread_join to return. However this solution isn't acceptable for my requirements. I discovered the pthread_setcanceltype function and its PTHREAD_CANCEL_ASYNCHRONOUS parameter, which looked like they would give me exactly what I needed : allow threads to be cancelled regardless of what they are doing (basically a pthread equivalent to TerminateThread). Unfortunately, my tests have been less than conclusive : pthread_setcanceltype doesn't seem to do anything at all. It tells me it succeeds, subsequent calls properly report the previous cancellation type as ASYNCHRONOUS. But pthread_join still hangs, and adding pthread_testcancel calls still makes it work... I'm working on a FreeBSD 4.4-release machine; I ran the same test under FreeBSD 4.3-release and got the same results. However, running it on a Linux box (Mandrake release, 2.4.x kernel), I get exactly the results I was expecting (that is, setting the cancellation type to asynchronous allows the thread to be cancelled at any time) see the end of this message for my test program So the questions are -am I doing something wrong or misinterpreting the man pages? -if not, is this a known bug? -if so, is there a workaround (or is it already fixed)? -if not, can someone investigate? (I once had a look at the libc_r code and ran away screaming) If this turns out to be a bug in libc_r, a suggestion for a work-around (even a hack) would be much appreciated, even if a proper fix is found and committed to CVS (requiring an upgrade from 4.4-release installations is something we'd rather avoid). now for some disclaimers : I'm aware that asynchronous cancellations (TerminateThread-style) are an Evil Thing To Do. Unfortunately I have no choice in the matter. I'm aware that there are some strict limitations on what a thread is "allowed" to do while its cancellation type is asynchronous. specifically, it should only call "cancel-safe" functions. Note that in my test program, the thread being cancelled doesn't call any functions at all after setting its cancellation type, so this shouldn't be an issue. now for the code : #include #include /* thread entry point */ void * thread_entry (void *arg) { int i; if(0!=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL)) { fprintf(stderr,"setcanceltype failed!\n"); } fprintf(stderr,"thread_entry entering loop\n"); while(1) { i++; /* uncomment this to insert a cancellation point */ /* pthread_testcancel();*/ } /* if we see this, it would mean the loop has been optimized out... */ fprintf(stderr, "after loop\n"); } int main(void) { pthread_t thread; pthread_attr_t attr; void *pthread_param; pthread_attr_init(&attr); fprintf(stderr,"creating thread\n"); pthread_create(&thread,&attr,&thread_entry,NULL); fprintf(stderr,"thread created; hit enter to cancel it...\n"); getchar(); fprintf(stderr,"cancelling...\n"); if(0!=pthread_cancel(thread)) { fprintf(stderr,"cancel failed!\n"); } fprintf(stderr,"after cancel, before join...\n"); if(0!=pthread_join(thread,&pthread_param)) { fprintf(stderr,"join failed!\n"); } fprintf(stderr,"after join\n"); } please ask if more details are needed Thanks in advance, Louis-Philippe Gagnon ~ louisphilippe@macadamian.com Macadamian Technologies "Software experts for the world's leading technology companies." http://www.macadamian.com To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message