summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-04-04 11:13:36 (GMT)
committersebres <sebres@users.sourceforge.net>2017-04-04 11:13:36 (GMT)
commita61a0e3df9df21ead49108d82842a48617cb0c09 (patch)
treee66a97c3efde500285a7899640d135a918b8612e
parent3637b82062f2363b7f70d0edca031396b2939efb (diff)
downloadtcl-fix_42202ba1e5ff566e.zip
tcl-fix_42202ba1e5ff566e.tar.gz
tcl-fix_42202ba1e5ff566e.tar.bz2
bug fix for [42202ba1e5ff566e0f9abb9f890e460fbc6c1c5c]: segfault by coro injectfix_42202ba1e5ff566e
rewritten callback for ::tcl::unsupported::inject, without leave the interpreter in unusable state (inaccurate environment exchange by adding eval callback), test covered now.
-rw-r--r--generic/tclBasic.c32
-rw-r--r--tests/coroutine.test39
2 files changed, 70 insertions, 1 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 4bddbce..f604ac1 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -8748,6 +8748,35 @@ TclNRCoroutineActivateCallback(
/*
*----------------------------------------------------------------------
*
+ * TclNREvalList --
+ *
+ * Callback to invoke command as list, used in order to delayed
+ * processing of canonical list command in sane environment.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TclNREvalList(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ int objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *listPtr = data[0];
+
+ Tcl_IncrRefCount(listPtr);
+
+ TclMarkTailcall(interp);
+ TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
+ TclListObjGetElements(NULL, listPtr, &objc, &objv);
+ return TclNREvalObjv(interp, objc, objv, 0, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* NRCoroInjectObjCmd --
*
* Implementation of [::tcl::unsupported::inject] command.
@@ -8799,7 +8828,8 @@ NRCoroInjectObjCmd(
*/
iPtr->execEnvPtr = corPtr->eePtr;
- TclNREvalObjEx(interp, Tcl_NewListObj(objc-2, objv+2), 0, NULL, INT_MIN);
+ TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc-2, objv+2),
+ NULL, NULL, NULL);
iPtr->execEnvPtr = savedEEPtr;
return TCL_OK;
diff --git a/tests/coroutine.test b/tests/coroutine.test
index 205da67..fd68567 100644
--- a/tests/coroutine.test
+++ b/tests/coroutine.test
@@ -741,6 +741,45 @@ test coroutine-7.12 {coro floor above street level #3008307} -body {
list
} -result {}
+test coroutine-8.0.0 {coro inject executed} -body {
+ coroutine demo apply {{} { foreach i {1 2} yield }}
+ demo
+ set ::result none
+ tcl::unsupported::inject demo set ::result inject-executed
+ demo
+ set ::result
+} -result {inject-executed}
+test coroutine-8.0.1 {coro inject after error} -body {
+ coroutine demo apply {{} { foreach i {1 2} yield; error test }}
+ demo
+ set ::result none
+ tcl::unsupported::inject demo set ::result inject-executed
+ lappend ::result [catch {demo} err] $err
+} -result {inject-executed 1 test}
+test coroutine-8.1.1 {coro inject, ticket 42202ba1e5ff566e} -body {
+ interp create slave
+ slave eval {
+ coroutine demo apply {{} { while {1} yield }}
+ demo
+ tcl::unsupported::inject demo set ::result inject-executed
+ }
+ interp delete slave
+} -result {}
+test coroutine-8.1.2 {coro inject with result, ticket 42202ba1e5ff566e} -body {
+ interp create slave
+ slave eval {
+ coroutine demo apply {{} { while {1} yield }}
+ demo
+ tcl::unsupported::inject demo set ::result inject-executed
+ }
+ slave eval demo
+ set result [slave eval {set ::result}]
+
+ interp delete slave
+ set result
+} -result {inject-executed}
+
+
# cleanup
unset lambda