diff options
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r-- | generic/tclIO.c | 45 |
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); |