summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index accf020..e4e8532 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIO.c,v 1.66 2003/03/06 20:14:51 mdejong Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.67 2003/04/11 17:39:51 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -6870,6 +6870,49 @@ UpdateInterest(chanPtr)
&& (statePtr->inQueueHead->nextRemoved <
statePtr->inQueueHead->nextAdded)) {
mask &= ~TCL_READABLE;
+
+ /*
+ * Andreas Kupries, April 11, 2003
+ *
+ * Some operating systems (Solaris 2.6 and higher (but not
+ * Solaris 2.5, go figure)) generate READABLE and
+ * EXCEPTION events when select()'ing [*] on a plain file,
+ * even if EOF was not yet reached. This is a problem in
+ * the following situation:
+ *
+ * - An extension asks to get both READABLE and EXCEPTION
+ * events.
+ * - It reads data into a buffer smaller than the buffer
+ * used by Tcl itself.
+ * - It does not process all events in the event queue, but
+ * only only one, at least in some situations.
+ *
+ * In that case we can get into a situation where
+ *
+ * - Tcl drops READABLE here, because it has data in its own
+ * buffers waiting to be read by the extension.
+ * - A READABLE event is syntesized via timer.
+ * - The OS still reports the EXCEPTION condition on the file.
+ * - And the extension gets the EXCPTION event first, and
+ * handles this as EOF.
+ *
+ * End result ==> Premature end of reading from a file.
+ *
+ * The concrete example is 'Expect', and its [expect]
+ * command (and at the C-level, deep in the bowels of
+ * Expect, 'exp_get_next_event'. See marker 'SunOS' for
+ * commentary in that function too).
+ *
+ * [*] As the Tcl notifier does. See also for marker
+ * 'SunOS' in file 'exp_event.c' of Expect.
+ *
+ * Our solution here is to drop the interest in the
+ * EXCEPTION events too. This compiles on all platforms,
+ * and also passes the testsuite on all of them.
+ */
+
+ mask &= ~TCL_EXCEPTION;
+
if (!statePtr->timer) {
statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc,
(ClientData) chanPtr);