diff options
-rw-r--r-- | generic/tclIO.c | 39 | ||||
-rw-r--r-- | tests/io.test | 6 | ||||
-rw-r--r-- | unix/tclUnixPipe.c | 4 | ||||
-rw-r--r-- | win/tclWinSock.c | 20 |
4 files changed, 42 insertions, 27 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 1c4a5b3..ed94bfe 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -2694,18 +2694,11 @@ FlushChannel( (chanPtr->typePtr->watchProc)(chanPtr->instanceData, statePtr->interestMask); } else { - - /* - * When we are calledFromAsyncFlush, that means a writable - * state on the channel triggered the call, so we should be - * able to write something. Either we did write something - * and wroteSome should be set, or there was nothing left to - * write in this call, and we've completed the BG flush. - * These are the two cases above. If we get here, that means - * there is some kind failure in the writable event machinery. - */ - - assert(!calledFromAsyncFlush); + /* TODO: If code reaches this point, it means a writable + * event is being handled on the channel, but the channel + * could not in fact be written to. This ought not happen, + * but Unix pipes appear to act this way (see io-53.4). + * Also can imagine broken reflected channels. */ } } @@ -3212,11 +3205,18 @@ Tcl_Close( stickyError = 0; - if ((statePtr->encoding != NULL) - && !(statePtr->outputEncodingFlags & TCL_ENCODING_START) - && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) { - statePtr->outputEncodingFlags |= TCL_ENCODING_END; - if (WriteChars(chanPtr, "", 0) < 0) { + if (GotFlag(statePtr, TCL_WRITABLE) && (statePtr->encoding != NULL) + && !(statePtr->outputEncodingFlags & TCL_ENCODING_START)) { + + int code = CheckChannelErrors(statePtr, TCL_WRITABLE); + + if (code == 0) { + statePtr->outputEncodingFlags |= TCL_ENCODING_END; + code = WriteChars(chanPtr, "", 0); + statePtr->outputEncodingFlags &= ~TCL_ENCODING_END; + statePtr->outputEncodingFlags |= TCL_ENCODING_START; + } + if (code < 0) { stickyError = Tcl_GetErrno(); } @@ -7646,8 +7646,9 @@ Tcl_NotifyChannel( */ if (GotFlag(statePtr, BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) { - FlushChannel(NULL, chanPtr, 1); - mask &= ~TCL_WRITABLE; + if (0 == FlushChannel(NULL, chanPtr, 1)) { + mask &= ~TCL_WRITABLE; + } } /* diff --git a/tests/io.test b/tests/io.test index 2296986..f1248b9 100644 --- a/tests/io.test +++ b/tests/io.test @@ -7120,12 +7120,17 @@ test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileeven for {set x 0} {$x < 12} {incr x} { append big $big } +# file delete $path(test1) file delete $path(pipe) set f1 [open $path(pipe) w] puts $f1 { puts ready fcopy stdin stdout -command { set x } vwait x +# set f [open $path(test1) w] +# fconfigure $f -translation lf +# puts $f "done" +# close $f } close $f1 set f1 [open "|[list [interpreter] $path(pipe)]" r+] @@ -7133,6 +7138,7 @@ test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileeven fconfigure $f1 -blocking 0 puts $f1 $big flush $f1 + after 500 set result "" fileevent $f1 read [namespace code { append result [read $f1 1024] diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 57be08f..d0a5e53 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -1125,7 +1125,7 @@ PipeWatchProc( if (psPtr->inFile) { newmask = mask & (TCL_READABLE | TCL_EXCEPTION); if (newmask) { - Tcl_CreateFileHandler(GetFd(psPtr->inFile), newmask, + Tcl_CreateFileHandler(GetFd(psPtr->inFile), mask, (Tcl_FileProc *) Tcl_NotifyChannel, (ClientData) psPtr->channel); } else { @@ -1135,7 +1135,7 @@ PipeWatchProc( if (psPtr->outFile) { newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION); if (newmask) { - Tcl_CreateFileHandler(GetFd(psPtr->outFile), newmask, + Tcl_CreateFileHandler(GetFd(psPtr->outFile), mask, (Tcl_FileProc *) Tcl_NotifyChannel, (ClientData) psPtr->channel); } else { diff --git a/win/tclWinSock.c b/win/tclWinSock.c index e18a3dd..8f565b9 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -1239,13 +1239,17 @@ WaitForSocketEvent( /* * Reset WSAAsyncSelect so we have a fresh set of events pending. + * Don't do that if we are waiting for a connect as we may miss + * a connect (bug 336441ed59). */ - SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, - (LPARAM) infoPtr); - - SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, - (LPARAM) infoPtr); + if ( 0 == (events & FD_CONNECT) ) { + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, + (LPARAM) infoPtr); + + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, + (LPARAM) infoPtr); + } while (1) { if (infoPtr->lastError) { @@ -2409,11 +2413,15 @@ SocketProc( case SOCKET_SELECT: infoPtr = (SocketInfo *) lParam; if (wParam == SELECT) { + /* + * Start notification by windows messages on socket events + */ + WSAAsyncSelect(infoPtr->socket, hwnd, SOCKET_MESSAGE, infoPtr->selectEvents); } else { /* - * Clear the selection mask + * UNSELECT: Clear the selection mask */ WSAAsyncSelect(infoPtr->socket, hwnd, 0, 0); |