Tcl Source Code

Check-in [b846182cdc]
Login

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

Overview
Comment:Minimal patch to fix iocmd-23.11. Might not be the best fix, but is *a* fix.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-5-branch
Files: files | file ages | folders
SHA1: b846182cdc2e35ab3d22101b6b0ab3aa36fba6ed
User & Date: dgp 2014-03-27 21:35:57
Context
2014-03-31
15:23
Cherry-pick [c54059aaad] from trunk: Added support for reporting TEA-like info via pkg-config. Add ... check-in: 70b7d58cae user: jan.nijtmans tags: core-8-5-branch
2014-03-28
20:29
Merge minimal fix for iocmd-23.11. Note that top channel regeneration is removed, so that Preserve/R... check-in: 4c19c39276 user: dgp tags: trunk
2014-03-27
21:35
Minimal patch to fix iocmd-23.11. Might not be the best fix, but is *a* fix. check-in: b846182cdc user: dgp tags: core-8-5-branch
19:14
Test iocmd-23.11 demos another segfault. check-in: d237824bfd user: dgp tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclIO.c.

3848
3849
3850
3851
3852
3853
3854

3855
3856
3857
3858
3859
3860
3861
    }

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;


    bufPtr = statePtr->inQueueHead;
    encoding = statePtr->encoding;

    /*
     * Preserved so we can restore the channel's state in case we don't find a
     * newline in the available input.







>







3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
    }

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    Tcl_Preserve(chanPtr);

    bufPtr = statePtr->inQueueHead;
    encoding = statePtr->encoding;

    /*
     * Preserved so we can restore the channel's state in case we don't find a
     * newline in the available input.
4140
4141
4142
4143
4144
4145
4146

4147
4148
4149
4150
4151
4152
4153
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);

    return copiedTotal;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetsObjBinary --







>







4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);
    Tcl_Release(chanPtr);
    return copiedTotal;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetsObjBinary --
4185
4186
4187
4188
4189
4190
4191

4192
4193
4194
4195
4196
4197
4198
    unsigned char *dst, *dstEnd, *eol, *eof, *byteArray;

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;


    bufPtr = statePtr->inQueueHead;

    /*
     * Preserved so we can restore the channel's state in case we don't find a
     * newline in the available input.
     */







>







4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
    unsigned char *dst, *dstEnd, *eol, *eof, *byteArray;

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    Tcl_Preserve(chanPtr);

    bufPtr = statePtr->inQueueHead;

    /*
     * Preserved so we can restore the channel's state in case we don't find a
     * newline in the available input.
     */
4384
4385
4386
4387
4388
4389
4390

4391
4392
4393
4394
4395
4396
4397
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);

    return copiedTotal;
}

/*
 *---------------------------------------------------------------------------
 *
 * FreeBinaryEncoding --







>







4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);
    Tcl_Release(chanPtr);
    return copiedTotal;
}

/*
 *---------------------------------------------------------------------------
 *
 * FreeBinaryEncoding --
4856
4857
4858
4859
4860
4861
4862

4863
4864
4865
4866
4867
4868
4869

    /*
     * Check for information in the push-back buffers. If there is some, use
     * it. Go to the driver only if there is none (anymore) and the caller
     * requests more bytes.
     */


    for (copied = 0; copied < bytesToRead; copied += copiedNow) {
	copiedNow = CopyBuffer(chanPtr, bufPtr + copied,
		bytesToRead - copied);
	if (copiedNow == 0) {
	    if (statePtr->flags & CHANNEL_EOF) {
		goto done;
	    }







>







4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874

    /*
     * Check for information in the push-back buffers. If there is some, use
     * it. Go to the driver only if there is none (anymore) and the caller
     * requests more bytes.
     */

    Tcl_Preserve(chanPtr);
    for (copied = 0; copied < bytesToRead; copied += copiedNow) {
	copiedNow = CopyBuffer(chanPtr, bufPtr + copied,
		bytesToRead - copied);
	if (copiedNow == 0) {
	    if (statePtr->flags & CHANNEL_EOF) {
		goto done;
	    }
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957

4958
4959
4960

4961
4962
4963
4964

4965
4966
4967
4968
4969
4970
4971
		if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
		    if (copied > 0) {
			/*
			 * Information that was copied earlier has precedence
			 * over EAGAIN/WOULDBLOCK handling.
			 */

			return copied;
		    }

		    SetFlag(statePtr, CHANNEL_BLOCKED);
		    result = EAGAIN;
		}

		Tcl_SetErrno(result);
		return -1;

	    }

	    return copied + nread;

	}
    }

  done:

    return copied;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_ReadChars --







|







|
>


|
>




>







4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
		if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
		    if (copied > 0) {
			/*
			 * Information that was copied earlier has precedence
			 * over EAGAIN/WOULDBLOCK handling.
			 */

			goto done;
		    }

		    SetFlag(statePtr, CHANNEL_BLOCKED);
		    result = EAGAIN;
		}

		Tcl_SetErrno(result);
		copied = -1;
		goto done;
	    }

	    copied += nread;
	    goto done;
	}
    }

  done:
    Tcl_Release(chanPtr);
    return copied;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_ReadChars --
5065
5066
5067
5068
5069
5070
5071

5072
5073
5074
5075
5076
5077
5078
    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    encoding = statePtr->encoding;
    factor = UTF_EXPANSION_FACTOR;


    if (appendFlag == 0) {
	if (encoding == NULL) {
	    Tcl_SetByteArrayLength(objPtr, 0);
	} else {
	    Tcl_SetObjLength(objPtr, 0);








>







5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    encoding = statePtr->encoding;
    factor = UTF_EXPANSION_FACTOR;
    Tcl_Preserve(chanPtr);

    if (appendFlag == 0) {
	if (encoding == NULL) {
	    Tcl_SetByteArrayLength(objPtr, 0);
	} else {
	    Tcl_SetObjLength(objPtr, 0);

5154
5155
5156
5157
5158
5159
5160

5161
5162
5163
5164
5165
5166
5167
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);

    return copied;
}

/*
 *---------------------------------------------------------------------------
 *
 * ReadBytes --







>







5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);
    Tcl_Release(chanPtr);
    return copied;
}

/*
 *---------------------------------------------------------------------------
 *
 * ReadBytes --
7695
7696
7697
7698
7699
7700
7701





7702
7703
7704
7705
7706
7707
7708
static void
UpdateInterest(
    Channel *chanPtr)		/* Channel to update. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int mask = statePtr->interestMask;






    /*
     * If there are flushed buffers waiting to be written, then we need to
     * watch for the channel to become writable.
     */

    if (statePtr->flags & BG_FLUSH_SCHEDULED) {







>
>
>
>
>







7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
static void
UpdateInterest(
    Channel *chanPtr)		/* Channel to update. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int mask = statePtr->interestMask;

    if (chanPtr->typePtr == NULL) {
	/* Do not update interest on a closed channel */
	return;
    }

    /*
     * If there are flushed buffers waiting to be written, then we need to
     * watch for the channel to become writable.
     */

    if (statePtr->flags & BG_FLUSH_SCHEDULED) {
8781
8782
8783
8784
8785
8786
8787

8788
8789
8790
8791
8792
8793
8794

    /*
     * If we have not encountered a sticky EOF, clear the EOF bit. Either way
     * clear the BLOCKED bit. We want to discover these anew during each
     * operation.
     */


    if (!(statePtr->flags & CHANNEL_STICKY_EOF)) {
	ResetFlag(statePtr, CHANNEL_EOF);
    }
    ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);

    for (copied = 0; copied < toRead; copied += copiedNow) {
	copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied,







>







8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810

    /*
     * If we have not encountered a sticky EOF, clear the EOF bit. Either way
     * clear the BLOCKED bit. We want to discover these anew during each
     * operation.
     */

    Tcl_Preserve(chanPtr);
    if (!(statePtr->flags & CHANNEL_STICKY_EOF)) {
	ResetFlag(statePtr, CHANNEL_EOF);
    }
    ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);

    for (copied = 0; copied < toRead; copied += copiedNow) {
	copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied,
8818
8819
8820
8821
8822
8823
8824

8825
8826
8827
8828
8829
8830
8831
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);

    return copied;
}

/*
 *----------------------------------------------------------------------
 *
 * CopyAndTranslateBuffer --







>







8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    UpdateInterest(chanPtr);
    Tcl_Release(chanPtr);
    return copied;
}

/*
 *----------------------------------------------------------------------
 *
 * CopyAndTranslateBuffer --

Changes to generic/tclIORChan.c.

567
568
569
570
571
572
573

574
575
576
577
578
579
580
     */

    rcId = NextHandle();
    rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
    chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
	    mode);
    rcPtr->chan = chan;

    chanPtr = (Channel *) chan;

    /*
     * Invoke 'initialize' and validate that the handler is present and ok.
     * Squash the channel if not.
     *
     * Note: The conversion of 'mode' back into a Tcl_Obj ensures that







>







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
     */

    rcId = NextHandle();
    rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
    chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
	    mode);
    rcPtr->chan = chan;
    Tcl_Preserve(chan);
    chanPtr = (Channel *) chan;

    /*
     * Invoke 'initialize' and validate that the handler is present and ok.
     * Squash the channel if not.
     *
     * Note: The conversion of 'mode' back into a Tcl_Obj ensures that
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
    if (chanPtr->typePtr != &tclRChannelType) {
	/*
	 * Delete a cloned ChannelType structure.
	 */

	ckfree((char*) chanPtr->typePtr);
    }


    n = rcPtr->argc - 2;
    for (i=0; i<n; i++) {
	Tcl_DecrRefCount(rcPtr->argv[i]);
    }

    /*







>







2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
    if (chanPtr->typePtr != &tclRChannelType) {
	/*
	 * Delete a cloned ChannelType structure.
	 */

	ckfree((char*) chanPtr->typePtr);
    }
    Tcl_Release(chanPtr);

    n = rcPtr->argc - 2;
    for (i=0; i<n; i++) {
	Tcl_DecrRefCount(rcPtr->argv[i]);
    }

    /*

Changes to tests/ioCmd.test.

1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
	set args [lassign $args sub id]
	if {$sub ne "read"} {return}
	close $id
	return {}
    }
    set c [chan create {r} foo]
    note [read $c]
    close $c
    rename foo {}
    set res
} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}

# --- === *** ###########################
# method write

test iocmd-24.1 {chan write, regular write} -match glob -body {
    set res {}
    proc foo {args} {







<


|







1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
	set args [lassign $args sub id]
	if {$sub ne "read"} {return}
	close $id
	return {}
    }
    set c [chan create {r} foo]
    note [read $c]

    rename foo {}
    set res
} -result {{read rc* 4096} {}}

# --- === *** ###########################
# method write

test iocmd-24.1 {chan write, regular write} -match glob -body {
    set res {}
    proc foo {args} {