summaryrefslogtreecommitdiffstats
path: root/generic/tclEvent.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2007-09-07 18:11:23 (GMT)
committerdgp <dgp@users.sourceforge.net>2007-09-07 18:11:23 (GMT)
commit700d951d9c38975ec0ecebf81e041ba444d0806b (patch)
treeabd3aa4c245bac66d347d25cc78064acf20cad48 /generic/tclEvent.c
parent65bc35e33b2f3c501acdaa45836327325e7e0da7 (diff)
downloadtcl-700d951d9c38975ec0ecebf81e041ba444d0806b.zip
tcl-700d951d9c38975ec0ecebf81e041ba444d0806b.tar.gz
tcl-700d951d9c38975ec0ecebf81e041ba444d0806b.tar.bz2
* generic/tclEvent.c ([::tcl::Bgerror]): Corrections to Tcl's
* tests/event.test: default [interp bgerror] handler so that when it falls back to a hidden [bgerror] in a safe interp, it gets the right error context data. [Bug 1790274].
Diffstat (limited to 'generic/tclEvent.c')
-rw-r--r--generic/tclEvent.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index 78b44c2..e9619bc 100644
--- a/generic/tclEvent.c
+++ b/generic/tclEvent.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: tclEvent.c,v 1.75 2007/09/07 15:51:25 dgp Exp $
+ * RCS: @(#) $Id: tclEvent.c,v 1.76 2007/09/07 18:11:24 dgp Exp $
*/
#include "tclInt.h"
@@ -310,6 +310,7 @@ TclDefaultBgErrorHandlerObjCmd(
Tcl_Obj *keyPtr, *valuePtr;
Tcl_Obj *tempObjv[2];
int code, level;
+ Tcl_InterpState saved;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "msg options");
@@ -358,6 +359,10 @@ TclDefaultBgErrorHandlerObjCmd(
}
Tcl_IncrRefCount(tempObjv[1]);
+ if (code != TCL_ERROR) {
+ Tcl_SetObjResult(interp, tempObjv[1]);
+ }
+
TclNewLiteralStringObj(keyPtr, "-errorcode");
Tcl_IncrRefCount(keyPtr);
Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
@@ -371,17 +376,21 @@ TclDefaultBgErrorHandlerObjCmd(
Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
Tcl_DecrRefCount(keyPtr);
if (valuePtr) {
- if (code != TCL_ERROR) {
- Tcl_SetObjResult(interp, tempObjv[1]);
- }
Tcl_IncrRefCount(valuePtr);
Tcl_AppendObjToErrorInfo(interp, valuePtr);
}
- /* Capture stack trace now, so we can report it if [bgerror] fails. */
- valuePtr = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
- Tcl_IncrRefCount(valuePtr);
+ if (code == TCL_ERROR) {
+ Tcl_SetObjResult(interp, tempObjv[1]);
+ }
+ /*
+ * Save interpreter state so we can restore it if multiple handler
+ * attempts are needed.
+ */
+
+ saved = Tcl_SaveInterpState(interp, code);
+
/* Invoke the bgerror command. */
Tcl_AllowExceptions(interp);
code = Tcl_EvalObjv(interp, 2, tempObjv, TCL_EVAL_GLOBAL);
@@ -397,7 +406,7 @@ TclDefaultBgErrorHandlerObjCmd(
*/
if (Tcl_IsSafe(interp)) {
- Tcl_ResetResult(interp);
+ Tcl_RestoreInterpState(interp, saved);
TclObjInvoke(interp, 2, tempObjv, TCL_INVOKE_HIDDEN);
} else {
Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);
@@ -407,11 +416,12 @@ TclDefaultBgErrorHandlerObjCmd(
Tcl_IncrRefCount(resultPtr);
if (Tcl_FindCommand(interp, "bgerror", NULL,
TCL_GLOBAL_ONLY) == NULL) {
- if (valuePtr) {
- Tcl_WriteObj(errChannel, valuePtr);
- Tcl_WriteChars(errChannel, "\n", -1);
- }
+ Tcl_RestoreInterpState(interp, saved);
+ Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp,
+ "errorInfo", NULL, TCL_GLOBAL_ONLY));
+ Tcl_WriteChars(errChannel, "\n", -1);
} else {
+ Tcl_DiscardInterpState(saved);
Tcl_WriteChars(errChannel,
"bgerror failed to handle background error.\n",-1);
Tcl_WriteChars(errChannel, " Original error: ", -1);
@@ -423,11 +433,15 @@ TclDefaultBgErrorHandlerObjCmd(
}
Tcl_DecrRefCount(resultPtr);
Tcl_Flush(errChannel);
+ } else {
+ Tcl_DiscardInterpState(saved);
}
}
code = TCL_OK;
+ } else {
+ Tcl_DiscardInterpState(saved);
}
- Tcl_DecrRefCount(valuePtr);
+
Tcl_DecrRefCount(tempObjv[0]);
Tcl_DecrRefCount(tempObjv[1]);
Tcl_ResetResult(interp);