From da40e7deb9d3e26315a495419b6ed50f0099bdc7 Mon Sep 17 00:00:00 2001 From: sebres Date: Sat, 20 Aug 2022 10:13:04 +0000 Subject: closes [baa51423c28a3baf]: needEvent must be initialized in cycle (for each watching channel) --- win/tclWinConsole.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index 23652de..30a09fd 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -861,21 +861,25 @@ ConsoleCheckProc( handleInfoPtr = FindConsoleInfo(chanInfoPtr); /* Pointer is safe to access as we are holding gConsoleLock */ - if (handleInfoPtr != NULL) { - AcquireSRWLockShared(&handleInfoPtr->lock); - /* Rememebr channel is read or write, never both */ - if (chanInfoPtr->watchMask & TCL_READABLE) { - if (RingBufferLength(&handleInfoPtr->buffer) > 0 - || handleInfoPtr->lastError != ERROR_SUCCESS) { - needEvent = 1; /* Input data available or error/EOF */ - } - } else if (chanInfoPtr->watchMask & TCL_WRITABLE) { - if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) { - needEvent = 1; /* Output space available */ - } + if (handleInfoPtr == NULL) { + continue; + } + + needEvent = 0; + AcquireSRWLockShared(&handleInfoPtr->lock); + /* Rememebr channel is read or write, never both */ + if (chanInfoPtr->watchMask & TCL_READABLE) { + if (RingBufferLength(&handleInfoPtr->buffer) > 0 + || handleInfoPtr->lastError != ERROR_SUCCESS + ) { + needEvent = 1; /* Input data available or error/EOF */ + } + } else if (chanInfoPtr->watchMask & TCL_WRITABLE) { + if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) { + needEvent = 1; /* Output space available */ } - ReleaseSRWLockShared(&handleInfoPtr->lock); } + ReleaseSRWLockShared(&handleInfoPtr->lock); if (needEvent) { ConsoleEvent *evPtr = (ConsoleEvent *)ckalloc(sizeof(ConsoleEvent)); -- cgit v0.12 From b00b14a7fd336ad3a98519a59657d143e4ef1ae0 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sat, 20 Aug 2022 12:16:10 +0000 Subject: Really closes [baa51423c28a3baf] --- win/tclWinConsole.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index 30a09fd..0e38c5b 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -862,19 +862,26 @@ ConsoleCheckProc( /* Pointer is safe to access as we are holding gConsoleLock */ if (handleInfoPtr == NULL) { + /* Stale event */ continue; } - + needEvent = 0; AcquireSRWLockShared(&handleInfoPtr->lock); - /* Rememebr channel is read or write, never both */ + /* Rememeber channel is read or write, never both */ if (chanInfoPtr->watchMask & TCL_READABLE) { if (RingBufferLength(&handleInfoPtr->buffer) > 0 - || handleInfoPtr->lastError != ERROR_SUCCESS - ) { + || handleInfoPtr->lastError != ERROR_SUCCESS) { needEvent = 1; /* Input data available or error/EOF */ } - } else if (chanInfoPtr->watchMask & TCL_WRITABLE) { + /* + * TCL_READABLE watch means someone is looking out for data being + * available, let reader thread know. + */ + handleInfoPtr->flags |= CONSOLE_DATA_AWAITED; + WakeConditionVariable(&handleInfoPtr->consoleThreadCV); + } + else if (chanInfoPtr->watchMask & TCL_WRITABLE) { if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) { needEvent = 1; /* Output space available */ } -- cgit v0.12 From 839d38fbba493c388c1d261f9b47b8b38e2b7cb4 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sat, 20 Aug 2022 16:56:10 +0000 Subject: Added test for bug [baa51423c2] --- tests/winConsole.test | 46 +++++++++++++++++++++++++++++++++++++++++----- win/tclWinConsole.c | 3 ++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/tests/winConsole.test b/tests/winConsole.test index 0daf54c..821a143 100644 --- a/tests/winConsole.test +++ b/tests/winConsole.test @@ -52,13 +52,21 @@ test console-input-1.0 {Console blocking gets} -constraints {win interactive} -b test console-input-1.1 {Console file channel: non-blocking gets} -constraints { win interactive +} -setup { + unset -nocomplain result + unset -nocomplain result2 } -body { set oldmode [fconfigure stdin] prompt "Type \"abc\" and hit Enter: " fileevent stdin readable { if {[gets stdin line] >= 0} { - set result $line + lappend result2 $line + if {[llength $result2] > 1} { + set result $result2 + } else { + prompt "Type \"def\" and hit Enter: " + } } elseif {[eof stdin]} { set result "gets failed" } @@ -66,7 +74,6 @@ test console-input-1.1 {Console file channel: non-blocking gets} -constraints { fconfigure stdin -blocking 0 -buffering line - set result {} vwait result #cleanup the fileevent @@ -74,7 +81,35 @@ test console-input-1.1 {Console file channel: non-blocking gets} -constraints { fconfigure stdin {*}$oldmode set result -} -result abc +} -result {abc def} + +test console-input-1.1.1 {Bug baa51423c28a: Console file channel: fileevent with blocking gets} -constraints { + win interactive +} -setup { + unset -nocomplain result + unset -nocomplain result2 +} -body { + prompt "Type \"abc\" and hit Enter: " + fileevent stdin readable { + if {[gets stdin line] >= 0} { + lappend result2 $line + if {[llength $result2] > 1} { + set result $result2 + } else { + prompt "Type \"def\" and hit Enter: " + } + } elseif {[eof stdin]} { + set result "gets failed" + } + } + + vwait result + + #cleanup the fileevent + fileevent stdin readable {} + set result + +} -result {abc def} test console-input-2.0 {Console blocking read} -constraints {win interactive} -setup { set oldmode [fconfigure stdin] @@ -94,6 +129,7 @@ test console-input-2.1 {Console file channel: non-blocking read} -constraints { set oldmode [fconfigure stdin] } -cleanup { fconfigure stdin {*}$oldmode + puts ""; # Because CRLF also would not have been echoed } -body { set input "" fconfigure stdin -blocking 0 -buffering line -inputmode raw @@ -262,10 +298,10 @@ test console-fconfigure-set-1.1 { fconfigure stdin -inputmode normal lappend result [yesno "\nWere the characters echoed?"] - prompt "\nType the keys \"c\", Ctrl-H, \"d\" and hit Enter. You should see characters echoed: " + prompt "Type the keys \"c\", Ctrl-H, \"d\" and hit Enter. You should see characters echoed: " lappend result [gets stdin] lappend result [fconfigure stdin -inputmode] - lappend result [yesno "\nWere the characters echoed (c replaced by d)?"] + lappend result [yesno "Were the characters echoed (c replaced by d)?"] set result } -result [list a\x08b raw 0 d normal 1] diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index 0e38c5b..4b2d1d3 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -876,7 +876,8 @@ ConsoleCheckProc( } /* * TCL_READABLE watch means someone is looking out for data being - * available, let reader thread know. + * available, let reader thread know. Note channel need not be + * ASYNC! (Bug [baa51423c2]) */ handleInfoPtr->flags |= CONSOLE_DATA_AWAITED; WakeConditionVariable(&handleInfoPtr->consoleThreadCV); -- cgit v0.12