summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2008-09-01 00:35:40 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2008-09-01 00:35:40 (GMT)
commit95660b09be94d6eb4b0482d33c78d8880e0c14cb (patch)
tree2579a1e6cb4beb302aec6d4a4b47951bd41033cb
parent4c5d518f5499a0a9f50e08bba0484cb6650b816a (diff)
downloadtcl-95660b09be94d6eb4b0482d33c78d8880e0c14cb.zip
tcl-95660b09be94d6eb4b0482d33c78d8880e0c14cb.tar.gz
tcl-95660b09be94d6eb4b0482d33c78d8880e0c14cb.tar.bz2
Improve the semantics of C-implemented destructors slightly.
-rw-r--r--ChangeLog8
-rw-r--r--generic/tclOO.c49
-rw-r--r--generic/tclOOMethod.c12
3 files changed, 50 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index c9225ea..8f5fab5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-09-01 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclOOMethod.c (InvokeProcedureMethod):
+ * generic/tclOO.c (ObjectRenamedTrace): Arrange for only methods that
+ involve callbacks into the Tcl interpreter to be skipped when the
+ interpreter is being torn down. Allows the semantics of destructors in
+ a dying interpreter to be more useful when they're implemented in C.
+
2008-08-29 Donal K. Fellows <dkf@users.sf.net>
* unix/Makefile.in: Ensure that all TclOO headers get installed.
diff --git a/generic/tclOO.c b/generic/tclOO.c
index 95926f2..b25f070 100644
--- a/generic/tclOO.c
+++ b/generic/tclOO.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclOO.c,v 1.15 2008/08/20 15:41:26 dkf Exp $
+ * RCS: @(#) $Id: tclOO.c,v 1.16 2008/09/01 00:35:42 dkf Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -548,6 +548,7 @@ ObjectRenamedTrace(
{
Object *oPtr = clientData;
Class *clsPtr;
+ CallContext *contextPtr;
/*
* If this is a rename and not a delete of the object, we just flush the
@@ -570,24 +571,22 @@ ObjectRenamedTrace(
AddRef(oPtr);
oPtr->flags |= OBJECT_DELETED;
- if (!Tcl_InterpDeleted(interp)) {
- CallContext *contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR);
- if (contextPtr != NULL) {
- int result;
- Tcl_InterpState state;
+ contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR);
+ if (contextPtr != NULL) {
+ int result;
+ Tcl_InterpState state;
- contextPtr->callPtr->flags |= DESTRUCTOR;
- contextPtr->skip = 0;
- state = Tcl_SaveInterpState(interp, TCL_OK);
- result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr,
- 0, NULL);
- if (result != TCL_OK) {
- Tcl_BackgroundError(interp);
- }
- Tcl_RestoreInterpState(interp, state);
- TclOODeleteContext(contextPtr);
+ contextPtr->callPtr->flags |= DESTRUCTOR;
+ contextPtr->skip = 0;
+ state = Tcl_SaveInterpState(interp, TCL_OK);
+ result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 0,
+ NULL);
+ if (result != TCL_OK) {
+ Tcl_BackgroundError(interp);
}
+ Tcl_RestoreInterpState(interp, state);
+ TclOODeleteContext(contextPtr);
}
/*
@@ -2134,11 +2133,18 @@ Tcl_ObjectContextInvokeNext(
if (contextPtr->index+1 >= contextPtr->callPtr->numChain) {
/*
- * We're at the end of the chain; generate an error message.
+ * We're at the end of the chain; generate an error message unless the
+ * interpreter is being torn down, in which case we might be getting
+ * here because of methods/destructors doing a [next] (or equivalent)
+ * unexpectedly.
*/
const char *methodType;
+ if (Tcl_InterpDeleted(interp)) {
+ return TCL_OK;
+ }
+
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
@@ -2195,11 +2201,18 @@ TclNRObjectContextInvokeNext(
if (contextPtr->index+1 >= contextPtr->callPtr->numChain) {
/*
- * We're at the end of the chain; generate an error message.
+ * We're at the end of the chain; generate an error message unless the
+ * interpreter is being torn down, in which case we might be getting
+ * here because of methods/destructors doing a [next] (or equivalent)
+ * unexpectedly.
*/
const char *methodType;
+ if (Tcl_InterpDeleted(interp)) {
+ return TCL_OK;
+ }
+
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
diff --git a/generic/tclOOMethod.c b/generic/tclOOMethod.c
index 75aef73..5371719 100644
--- a/generic/tclOOMethod.c
+++ b/generic/tclOOMethod.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclOOMethod.c,v 1.17 2008/08/23 18:53:12 msofer Exp $
+ * RCS: @(#) $Id: tclOOMethod.c,v 1.18 2008/09/01 00:35:42 dkf Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -643,6 +643,16 @@ InvokeProcedureMethod(
* call frame's lifetime). */
/*
+ * If the interpreter was deleted, we just skip to the next thing in the
+ * chain.
+ */
+
+ if (Tcl_InterpDeleted(interp)) {
+ return TclNRObjectContextInvokeNext(interp, context, objc, objv,
+ Tcl_ObjectContextSkippedArgs(context));
+ }
+
+ /*
* Allocate the special frame data.
*/