From b21d03a76b28dee1c88a2ccc05dd815364babd83 Mon Sep 17 00:00:00 2001 From: vasiljevic Date: Tue, 11 Jul 2006 13:18:10 +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 818eeb8..4565862 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-10 Jeff Hobbs * generic/tclIO.c (Tcl_CreateChannel): allow Tcl std channel diff --git a/generic/tclAsync.c b/generic/tclAsync.c index 76e3e28..c99cea9 100644 --- a/generic/tclAsync.c +++ b/generic/tclAsync.c @@ -12,7 +12,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.6 2001/08/30 07:50:18 davygrvy Exp $ + * RCS: @(#) $Id: tclAsync.c,v 1.6.12.1 2006/07/11 13:18:10 vasiljevic Exp $ */ #include "tclInt.h" @@ -286,20 +286,29 @@ Tcl_AsyncDelete(async) 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