Index: generic/tclIO.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIO.c,v
retrieving revision 1.172
diff -u -r1.172 tclIO.c
--- generic/tclIO.c	24 Feb 2010 10:45:04 -0000	1.172
+++ generic/tclIO.c	16 Mar 2010 22:36:55 -0000
@@ -4778,6 +4778,13 @@
      */
 
   done:
+    /*
+     * Regenerate the top channel, in case it was changed due to
+     * self-modifying reflected transforms.
+     */
+
+    chanPtr = statePtr->topChanPtr;
+
     UpdateInterest(chanPtr);
     return copiedTotal;
 }
Index: generic/tclIORTrans.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIORTrans.c,v
retrieving revision 1.14
diff -u -r1.14 tclIORTrans.c
--- generic/tclIORTrans.c	5 Mar 2010 22:50:32 -0000	1.14
+++ generic/tclIORTrans.c	16 Mar 2010 22:36:55 -0000
@@ -721,7 +721,7 @@
      * structure.
      */
 
-    FreeReflectedTransform(rtPtr);
+    Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
     return TCL_ERROR;
 
 #undef CHAN
@@ -931,7 +931,7 @@
 	}
 #endif
 
-	FreeReflectedTransform(rtPtr);
+	Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
 	return EOK;
     }
 
@@ -1030,7 +1030,7 @@
     }
 #endif
 
-    FreeReflectedTransform(rtPtr);
+    Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
     return (result == TCL_OK) ? EOK : EINVAL;
 }
 
@@ -1072,8 +1072,9 @@
 	return -1;
     }
 
-    gotBytes = 0;
+    Tcl_Preserve(rtPtr);
 
+    gotBytes = 0;
     while (toRead > 0) {
 	/*
 	 * Loop until the request is satisfied (or no data available from
@@ -1086,7 +1087,7 @@
 	gotBytes += copied;
 
 	if (toRead == 0) {
-	    return gotBytes;
+	    goto stop;
 	}
 
 	/*
@@ -1109,10 +1110,10 @@
 	    int maxRead = -1;
 
 	    if (!TransformLimit(rtPtr, errorCodePtr, &maxRead)) {
-		return -1;
+		goto error;
 	    }
 	    if (maxRead == 0) {
-		return gotBytes;
+		goto stop;
 	    } else if (maxRead > 0) {
 		if (maxRead < toRead) {
 		    toRead = maxRead;
@@ -1121,7 +1122,7 @@
 	}
 
 	if (toRead <= 0) {
-	    return gotBytes;
+	    goto stop;
 	}
 
 	readBytes = Tcl_ReadRaw(rtPtr->parent, buf, toRead);
@@ -1137,11 +1138,11 @@
 		 * we report that instead of the request to re-try.
 		 */
 
-		return gotBytes;
+		goto stop;
 	    }
 
 	    *errorCodePtr = Tcl_GetErrno();
-	    return -1;
+	    goto error;
 	}
 
 	if (readBytes == 0) {
@@ -1162,16 +1163,16 @@
 
 		if ((gotBytes == 0) && rtPtr->nonblocking) {
 		    *errorCodePtr = EWOULDBLOCK;
-		    return -1;
+		    goto error;
 		}
-		return gotBytes;
+		goto stop;
 	    } else {
 		/*
 		 * Eof in parent.
 		 */
 
 		if (rtPtr->readIsDrained) {
-		    return gotBytes;
+		    goto stop;
 		}
 
 		/*
@@ -1181,7 +1182,7 @@
 
 		if (HAS(rtPtr->methods, METH_DRAIN)) {
 		    if (!TransformDrain(rtPtr, errorCodePtr)) {
-			return -1;
+			goto error;
 		    }
 		}
 
@@ -1190,7 +1191,7 @@
 		     * The drain delivered nothing.
 		     */
 
-		    return gotBytes;
+		    goto stop;
 		}
 
 		/*
@@ -1209,11 +1210,17 @@
 	 */
 
 	if (!TransformRead(rtPtr, errorCodePtr, UCHARP(buf), readBytes)) {
-	    return -1;
+	    goto error;
 	}
     } /* while toRead > 0 */
 
+  stop:
+    Tcl_Release(rtPtr);
     return gotBytes;
+
+  error:
+    gotBytes = -1;
+    goto stop;
 }
 
 /*
@@ -1266,6 +1273,8 @@
      * we do when explicitly seeking as well.
      */
 
+    Tcl_Preserve(rtPtr);
+
     if ((rtPtr->methods & FLAG(METH_CLEAR))) {
 	TransformClear(rtPtr);
     }
@@ -1277,10 +1286,12 @@
      */
 
     if (!TransformWrite(rtPtr, errorCodePtr, UCHARP(buf), toWrite)) {
+	Tcl_Release(rtPtr);
 	return -1;
     }
 
     *errorCodePtr = EOK;
+    Tcl_Release(rtPtr);
     return toWrite;
 }
 
@@ -1331,6 +1342,8 @@
      * request down and the result back up unchanged.
      */
 
+    Tcl_Preserve(rtPtr);
+
     if (((seekMode != SEEK_CUR) || (offset != 0))
 	    && (HAS(rtPtr->methods, METH_CLEAR)
 	    || HAS(rtPtr->methods, METH_FLUSH))) {
@@ -1353,6 +1366,7 @@
 
 	if (HAS(rtPtr->methods, METH_FLUSH)) {
 	    if (!TransformFlush(rtPtr, errorCodePtr, FLUSH_DISCARD)) {
+		Tcl_Release(rtPtr);
 		return -1;
 	    }
 	}
@@ -1382,6 +1396,7 @@
     }
 
     *errorCodePtr = EOK;
+    Tcl_Release(rtPtr);
     return curPos;
 }
 
@@ -1971,7 +1986,7 @@
      */
 
     sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */);
-    Tcl_Preserve(rtPtr->interp);
+    Tcl_Preserve(rtPtr);
     result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL);
 
     /*
@@ -2016,7 +2031,7 @@
 	Tcl_IncrRefCount(resObj);
     }
     Tcl_RestoreInterpState(rtPtr->interp, sr);
-    Tcl_Release(rtPtr->interp);
+    Tcl_Release(rtPtr);
 
     /*
      * Cleanup of the dynamic parts of the command.
@@ -2531,7 +2546,8 @@
 	rtmPtr = GetThreadReflectedTransformMap();
 	hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
 	Tcl_DeleteHashEntry(hPtr);
-	FreeReflectedTransform(rtPtr);
+
+	Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
 	break;
 
     case ForwardedInput: {
