diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2008-05-20 22:22:14 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2008-05-20 22:22:14 (GMT) |
commit | a1ca307c098bd1b12e73b18eb500707296e084ca (patch) | |
tree | d20e5333aee55b716637ba25b7de217b6e49fef6 /generic/tclNamesp.c | |
parent | ecf4164c6f084705cf96b0610c3bfc82c44a094f (diff) | |
download | tcl-a1ca307c098bd1b12e73b18eb500707296e084ca.zip tcl-a1ca307c098bd1b12e73b18eb500707296e084ca.tar.gz tcl-a1ca307c098bd1b12e73b18eb500707296e084ca.tar.bz2 |
Correct logic for handling error cases when setting the namespace unknown handler.
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r-- | generic/tclNamesp.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index f7fa9c1..691c62f 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -23,7 +23,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclNamesp.c,v 1.162 2008/03/02 18:46:39 msofer Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.163 2008/05/20 22:22:16 dkf Exp $ */ #include "tclInt.h" @@ -4296,45 +4296,58 @@ Tcl_SetNamespaceUnknownHandler( Tcl_Namespace *nsPtr, /* Namespace which is being updated. */ Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */ { - int lstlen; + int lstlen = 0; Namespace *currNsPtr = (Namespace *)nsPtr; - if (currNsPtr->unknownHandlerPtr != NULL) { - /* - * Remove old handler first. - */ + /* + * Ensure that we check for errors *first* before we change anything. + */ - Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr); - currNsPtr->unknownHandlerPtr = NULL; + if (handlerPtr != NULL) { + if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { + /* + * Not a list. + */ + + return TCL_ERROR; + } + if (lstlen > 0) { + /* + * We are going to be saving this handler. Increment the reference + * count before decrementing the refcount on the previous handler, + * so that nothing strange can happen if we are told to set the + * handler to the previous value. + */ + + Tcl_IncrRefCount(handlerPtr); + } } /* - * If NULL or an empty list is passed, then reset to the default - * handler. + * Remove old handler next. */ - if (handlerPtr == NULL) { - currNsPtr->unknownHandlerPtr = NULL; - } else if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { - /* - * Not a list. - */ + if (currNsPtr->unknownHandlerPtr != NULL) { + Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr); + } - return TCL_ERROR; - } else if (lstlen == 0) { + /* + * Install the new handler. + */ + + if (lstlen > 0) { /* - * Empty list - reset to default. + * Just store the handler. It already has the correct reference count. */ - currNsPtr->unknownHandlerPtr = NULL; + currNsPtr->unknownHandlerPtr = handlerPtr; } else { /* - * Increment ref count and store. The reference count is decremented - * either in the code above, or when the namespace is deleted. + * If NULL or an empty list is passed, this resets to the default + * handler. */ - Tcl_IncrRefCount(handlerPtr); - currNsPtr->unknownHandlerPtr = handlerPtr; + currNsPtr->unknownHandlerPtr = NULL; } return TCL_OK; } |