From f18c557644d1683a67a7aadaf26d957dacc797d1 Mon Sep 17 00:00:00 2001 From: vasiljevic Date: Tue, 11 Jul 2006 14:29:14 +0000 Subject: Made Tcl_AsyncDelete() more tolerant when called after all thread TSD has been garbage-collected. --- ChangeLog | 5 +++++ generic/tclAsync.c | 37 +++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2b53d1..5164c49 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-07-11 Zoran Vasiljevic + + * generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant + when called after all thread TSD has been garbage-collected. + 2006-07-05 Don Porter * generic/tclParseExpr.c: Completely new expression parser diff --git a/generic/tclAsync.c b/generic/tclAsync.c index 5c3a535..f53e9fa 100644 --- a/generic/tclAsync.c +++ b/generic/tclAsync.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclAsync.c,v 1.9 2005/11/07 15:19:29 dkf Exp $ + * RCS: @(#) $Id: tclAsync.c,v 1.10 2006/07/11 14:29:14 vasiljevic Exp $ */ #include "tclInt.h" @@ -270,20 +270,29 @@ Tcl_AsyncDelete( AsyncHandler *asyncPtr = (AsyncHandler *) async; AsyncHandler *prevPtr; + /* + * Conservatively check the existence of the linked list of + * registered handlers, as we may come at this point even + * when the TSD's for the current thread have been already + * garbage-collected. + */ + Tcl_MutexLock(&tsdPtr->asyncMutex); - if (tsdPtr->firstHandler == asyncPtr) { - tsdPtr->firstHandler = asyncPtr->nextPtr; - if (tsdPtr->firstHandler == NULL) { - tsdPtr->lastHandler = NULL; - } - } else { - prevPtr = tsdPtr->firstHandler; - while (prevPtr->nextPtr != asyncPtr) { - prevPtr = prevPtr->nextPtr; - } - prevPtr->nextPtr = asyncPtr->nextPtr; - if (tsdPtr->lastHandler == asyncPtr) { - tsdPtr->lastHandler = prevPtr; + if (tsdPtr->firstHandler != NULL ) { + if (tsdPtr->firstHandler == asyncPtr) { + tsdPtr->firstHandler = asyncPtr->nextPtr; + if (tsdPtr->firstHandler == NULL) { + tsdPtr->lastHandler = NULL; + } + } else { + prevPtr = tsdPtr->firstHandler; + while (prevPtr->nextPtr != asyncPtr) { + prevPtr = prevPtr->nextPtr; + } + prevPtr->nextPtr = asyncPtr->nextPtr; + if (tsdPtr->lastHandler == asyncPtr) { + tsdPtr->lastHandler = prevPtr; + } } } Tcl_MutexUnlock(&tsdPtr->asyncMutex); -- cgit v0.12