Check-in [0d6ad67b02]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Correct the interest masks in the Tcl_CreateFileHandler() calls in PipeWatchProc(). When we are interested in both readable and writable events of a command pipeline channel, we only want the readable from the read end of the pipe, and the writable from the write end of the pipe.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0d6ad67b02763df44c2748f58ebec245d6f950d0
User & Date: dgp 2014-05-31 02:40:00.659
Context
2014-06-03
07:26
[1b0266d8bb] Working towards ensuring that all dict operations are sufficiently strict. check-in: 064f886aae user: dkf tags: bug-1b0266d8bb
2014-06-02
10:57
Improve robustness of the socket tests against systems that support IPv6, but don't resolve localhos... check-in: 8a95c913e1 user: max tags: trunk
2014-05-31
20:47
merge trunk check-in: 4acc825692 user: dkf tags: dkf-http-cookies
14:12
Backout checkin 84f992ce50. This fixes test socket-14.11.1 and creates failure in tests *io-1.9. B... Closed-Leaf check-in: 5f5b6fc4b2 user: dgp tags: bug-734138ded8
02:40
Correct the interest masks in the Tcl_CreateFileHandler() calls in PipeWatchProc(). When we are inte... check-in: 0d6ad67b02 user: dgp tags: trunk
02:30
Correct the interest masks in the Tcl_CreateFileHandler() calls in PipeWatchProc(). When we are int... check-in: 74a2238ecc user: dgp tags: core-8-5-branch
2014-05-29
15:04
Refinements of FlushChannel() and its callers. Notably includes removal of the flag BUFFER_READY. check-in: 37bcb4b42d user: dgp tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tclIO.c.
2773
2774
2775
2776
2777
2778
2779
2780


2781






2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
    if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
	if (wroteSome) {
	    goto done;
	} else if (statePtr->outQueueHead == NULL) {
	    ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
	    ChanWatch(chanPtr, statePtr->interestMask);
	} else {
	    /* 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. */

	}
    }

    /*
     * If the channel is flagged as closed, delete it when the refCount drops
     * to zero, the output queue is empty and there is no output in the
     * current output buffer.







|
>
>
|
>
>
>
>
>
>
|
<
<
>







2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790


2791
2792
2793
2794
2795
2796
2797
2798
    if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
	if (wroteSome) {
	    goto done;
	} else if (statePtr->outQueueHead == NULL) {
	    ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
	    ChanWatch(chanPtr, 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);
	}
    }

    /*
     * If the channel is flagged as closed, delete it when the refCount drops
     * to zero, the output queue is empty and there is no output in the
     * current output buffer.
Changes to tests/io.test.
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
} "ready line1 line2 {done\n}"
test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileevent fcopy} {
    set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
    variable x
    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+]
    set result [gets $f1]
    fconfigure $f1 -blocking 0
    puts $f1 $big
    flush $f1
    after 500
    set result ""
    fileevent $f1 read [namespace code {
	append result [read $f1 1024]
	if {[string length $result] >= [string length $big]} {
	    set x done
	}
    }]







<






<
<
<
<







<







7140
7141
7142
7143
7144
7145
7146

7147
7148
7149
7150
7151
7152




7153
7154
7155
7156
7157
7158
7159

7160
7161
7162
7163
7164
7165
7166
} "ready line1 line2 {done\n}"
test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileevent fcopy} {
    set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
    variable x
    for {set x 0} {$x < 12} {incr x} {
	append big $big
    }

    file delete $path(pipe)
    set f1 [open $path(pipe) w]
    puts $f1 {
	puts ready
	fcopy stdin stdout -command { set x }
	vwait x




    }
    close $f1
    set f1 [open "|[list [interpreter] $path(pipe)]" r+]
    set result [gets $f1]
    fconfigure $f1 -blocking 0
    puts $f1 $big
    flush $f1

    set result ""
    fileevent $f1 read [namespace code {
	append result [read $f1 1024]
	if {[string length $result] >= [string length $big]} {
	    set x done
	}
    }]
Changes to unix/tclUnixPipe.c.
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
{
    PipeState *psPtr = instanceData;
    int newmask;

    if (psPtr->inFile) {
	newmask = mask & (TCL_READABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->inFile), mask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->inFile));
	}
    }
    if (psPtr->outFile) {
	newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->outFile), mask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
	}
    }
}








|








|







1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
{
    PipeState *psPtr = instanceData;
    int newmask;

    if (psPtr->inFile) {
	newmask = mask & (TCL_READABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->inFile), newmask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->inFile));
	}
    }
    if (psPtr->outFile) {
	newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->outFile), newmask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
	}
    }
}