summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclIORChan.c31
-rw-r--r--tests/io.test186
-rw-r--r--tests/ioCmd.test8
3 files changed, 219 insertions, 6 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c
index bbb5b88..b059c79 100644
--- a/generic/tclIORChan.c
+++ b/generic/tclIORChan.c
@@ -741,6 +741,27 @@ TclChanCreateObjCmd(
*----------------------------------------------------------------------
*/
+typedef struct PostEvent {
+ Tcl_Event event; /* Basic event data, has to be first item */
+ Tcl_Channel chan;
+ int events;
+} PostEvent;
+
+static int
+CallNotify(
+ Tcl_Event *evPtr,
+ int flags)
+{
+ PostEvent *pevPtr = (PostEvent *)evPtr;
+ Channel *chanPtr = (Channel *)pevPtr->chan;
+
+ if (chanPtr->typePtr != NULL) {
+ Tcl_NotifyChannel(pevPtr->chan, pevPtr->events);
+ }
+ TclChannelRelease(pevPtr->chan);
+ return 1;
+}
+
int
TclChanPostEventObjCmd(
ClientData clientData,
@@ -769,6 +790,7 @@ TclChanPostEventObjCmd(
int events; /* Mask of events to post */
ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */
Tcl_HashEntry* hPtr; /* Entry in the above map */
+ PostEvent *pevPtr;
/*
* Number of arguments...
@@ -857,7 +879,12 @@ TclChanPostEventObjCmd(
* We have the channel and the events to post.
*/
- Tcl_NotifyChannel(chan, events);
+ pevPtr = (PostEvent *)ckalloc(sizeof(PostEvent));
+ pevPtr->event.proc = CallNotify;
+ pevPtr->chan = chan;
+ pevPtr->events = events;
+ TclChannelPreserve(chan);
+ Tcl_QueueEvent((Tcl_Event *)pevPtr, TCL_QUEUE_HEAD);
/*
* Squash interp results left by the event script.
@@ -1508,7 +1535,7 @@ ReflectWatch(
mask &= rcPtr->mode;
- if (mask == rcPtr->interest) {
+ if (0 && mask == rcPtr->interest) {
/*
* Same old, same old, why should we do something?
*/
diff --git a/tests/io.test b/tests/io.test
index 50c5808..914cbca 100644
--- a/tests/io.test
+++ b/tests/io.test
@@ -7886,6 +7886,192 @@ test io-53.15 {[ed29c4da21] DoRead: fblocked seen as error} -setup {
removeFile out
} -result 100
+test io-53.18 {[32ae34e63a] recursive CopyData} -setup {
+ proc driver {cmd args} {
+ variable buffer
+ variable index
+ set chan [lindex $args 0]
+ switch -- $cmd {
+ initialize {
+ set index($chan) 0
+ set buffer($chan) [encoding convertto utf-8 \
+ [string repeat a 100]]
+ return {initialize finalize watch read}
+ }
+ finalize {
+ unset index($chan) buffer($chan)
+ return
+ }
+ watch {
+ if {"read" in [lindex $args 1]} {
+ chan postevent $chan read
+ }
+ return
+ }
+ read {
+ set n [lindex $args 1]
+ set new [expr {$index($chan) + $n}]
+ set result [string range $buffer($chan) $index($chan) $new-1]
+ set index($chan) $new
+ return $result
+ }
+ }
+ }
+ proc more {c outChan bytes args} {
+ if {[eof $c]} {
+ set ::done eof
+ catch {close $c}
+ return
+ }
+ if {[llength $args]} {
+ set ::done error
+ } else {
+ chan copy $c $outChan -command [list [namespace which more] $c $outChan]
+ }
+ }
+ set c [chan create read [namespace which driver]]
+ chan configure $c -encoding utf-8
+ set out [makeFile {} out]
+ set outChan [open $out w]
+ # Different encoding to force use of DoReadChars()
+ chan configure $outChan -encoding iso8859-1
+} -body {
+ after 100 {set ::done timeout}
+ chan copy $c $outChan -size 99 -command [list [namespace which more] $c $outChan]
+ vwait ::done
+ set ::done
+} -cleanup {
+ close $outChan
+ removeFile out
+ rename driver {}
+ rename more {}
+ unset ::done
+} -result eof
+
+test io-53.19 {[32ae34e63a] stop ReflectWatch filtering} -setup {
+ proc driver {cmd args} {
+ variable buffer
+ variable index
+ set chan [lindex $args 0]
+ switch -- $cmd {
+ initialize {
+ set index($chan) 0
+ set buffer($chan) [encoding convertto utf-8 \
+ [string repeat a 100]]
+ return {initialize finalize watch read}
+ }
+ finalize {
+ unset index($chan) buffer($chan)
+ return
+ }
+ watch {
+ if {"read" in [lindex $args 1]} {
+ chan postevent $chan read
+ }
+ return
+ }
+ read {
+ set n [lindex $args 1]
+ set new [expr {$index($chan) + $n}]
+ set result [string range $buffer($chan) $index($chan) $new-1]
+ set index($chan) $new
+ return $result
+ }
+ }
+ }
+ proc more {c outChan bytes args} {
+ if {[eof $c]} {
+ set ::done eof
+ catch {close $c}
+ return
+ }
+ if {[llength $args]} {
+ set ::done error
+ } else {
+ chan copy $c $outChan -size 30 -command [list [namespace which more] $c $outChan]
+ }
+ }
+ set c [chan create read [namespace which driver]]
+ chan configure $c -encoding utf-8 -buffersize 20
+ set out [makeFile {} out]
+ set outChan [open $out w]
+ # Different encoding to force use of DoReadChars()
+ chan configure $outChan -encoding iso8859-1
+} -body {
+ after 100 {set ::done timeout}
+ chan copy $c $outChan -size 30 -command [list [namespace which more] $c $outChan]
+ vwait ::done
+ set ::done
+} -cleanup {
+ catch {close $outChan}
+ removeFile out
+ rename driver {}
+ rename more {}
+ unset ::done
+} -result eof
+
+test io-53.20 {[e0a7b3e5f8] DoRead calls to UpdateInterest} -setup {
+ proc driver {cmd args} {
+ variable buffer
+ variable index
+ set chan [lindex $args 0]
+ switch -- $cmd {
+ initialize {
+ set index($chan) 0
+ set buffer($chan) [encoding convertto utf-8 \
+ [string repeat a 100]]
+ return {initialize finalize watch read}
+ }
+ finalize {
+ unset index($chan) buffer($chan)
+ return
+ }
+ watch {
+ if {"read" in [lindex $args 1]} {
+ chan postevent $chan read
+ }
+ return
+ }
+ read {
+ set n [lindex $args 1]
+ set new [expr {$index($chan) + $n}]
+ set result [string range $buffer($chan) $index($chan) $new-1]
+ set index($chan) $new
+ return $result
+ }
+ }
+ }
+ proc more {c outChan bytes args} {
+ if {[eof $c]} {
+ set ::done eof
+ catch {close $c}
+ return
+ }
+ if {[llength $args]} {
+ set ::done error
+ } else {
+ chan copy $c $outChan -size 10 -command [list [namespace which more] $c $outChan]
+ }
+ }
+ set c [chan create read [namespace which driver]]
+ chan configure $c -encoding utf-8 -buffersize 20
+ set out [makeFile {} out]
+ set outChan [open $out w]
+ # Same encoding to force use of DoRead()
+ chan configure $outChan -encoding utf-8
+} -body {
+ after 100 {set ::done timeout}
+ chan copy $c $outChan -size 10 -command [list [namespace which more] $c $outChan]
+ vwait ::done
+ set ::done
+} -cleanup {
+ catch {close $outChan}
+ removeFile out
+ rename driver {}
+ rename more {}
+ unset ::done
+} -result eof
+
test io-54.1 {Recursive channel events} {socket fileevent} {
# This test checks to see if file events are delivered during recursive
# event loops when there is buffered data on the channel.
diff --git a/tests/ioCmd.test b/tests/ioCmd.test
index 5a76d48..c706e50 100644
--- a/tests/ioCmd.test
+++ b/tests/ioCmd.test
@@ -1949,26 +1949,26 @@ test iocmd-31.6 {chan postevent, posted events do happen} -match glob -body {
set c [chan create {r w} foo]
note [fileevent $c readable {note TOCK}]
set stop [after 10000 {note TIMEOUT}]
- after 1000 {note [chan postevent $c r]}
+ after 1000 {chan postevent $c r}
vwait ::res
catch {after cancel $stop}
close $c
rename foo {}
set res
-} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
+} -result {{watch rc* read} {} TOCK {watch rc* {}}}
test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
set res {}
proc foo {args} {oninit; onfinal; track; return}
set c [chan create {r w} foo]
note [fileevent $c writable {note TOCK}]
set stop [after 10000 {note TIMEOUT}]
- after 1000 {note [chan postevent $c w]}
+ after 1000 {chan postevent $c w}
vwait ::res
catch {after cancel $stop}
close $c
rename foo {}
set res
-} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}
+} -result {{watch rc* write} {} TOCK {watch rc* {}}}
test iocmd-31.8 {chan postevent after close throws error} -match glob -setup {
proc foo {args} {oninit; onfinal; track; return}
proc dummy args { return }