Changes On Branch 2e7300065a5c7611
Not logged in

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

Changes In Branch fix-815e246806-8-6 Through [2e7300065a] Excluding Merge-Ins

This is equivalent to a diff from 9cfddbdc92 to 2e7300065a

2018-06-11
11:11
fixed [815e246806] for 8.6th case if channel switches owner in fileevent via thread::transfer and th... check-in: 922ee82dde user: sebres tags: fix-815e246806-8-6
2018-06-09
07:44
Merge 8.5 (= update Unicode data to Unicode version 11.0) check-in: 3fd6be3568 user: jan.nijtmans tags: core-8-6-branch
2018-06-08
22:34
**interim commit** fixed for 8.6th case if channel switches owner via thread::transfer check-in: 2e7300065a user: sebres tags: fix-815e246806-8-6
19:02
merge atomic fix from fix-815e246806-8-5 check-in: 1d2c1768c9 user: sebres tags: fix-815e246806-8-6
13:33
merge fix for [815e246806] from 8.5th branch fix-815e246806-8-5 check-in: f44a1ddd60 user: sebres tags: fix-815e246806-8-6
13:02
merge 8.5 (empty merge point, no functional changes, because does not affect 8.6) check-in: 9cfddbdc92 user: sebres tags: core-8-6-branch
12:50
resolves some warnings by compiling with new gcc-versions (>= 7.x): - '*' in boolean context, sugg... check-in: 9ea4420be8 user: sebres tags: core-8-5-branch
2018-06-04
13:52
merge 8.5 check-in: a9a4a69e99 user: sebres tags: core-8-6-branch

Changes to generic/tclIO.c.
1172
1173
1174
1175
1176
1177
1178







1179

1180
1181
1182
1183
1184
1185
1186
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194







+
+
+
+
+
+
+

+







		return;
	    }

	    Tcl_Panic("Tcl_RegisterChannel: duplicate channel names");
	}
	Tcl_SetHashValue(hPtr, chanPtr);
    }

    /*
     * Increase ref-count of the state and channel (note the transfer-process to
     * other thread could temporary share the channel in two threads (especially 
     * if initiated from event-handler like TclChannelEventScriptInvoker,
     * see [815e246806]).
     */
    statePtr->refCount++;
    TclChannelPreserve(chan);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UnregisterChannel --
 *
1374
1375
1376
1377
1378
1379
1380


1381
1382
1383
1384
1385
1386
1387
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397







+
+







	 * shared between several interpreters, or if the channel has async
	 * flushing active.
	 */

	CleanupChannelHandlers(interp, chanPtr);
    }

    /* Opposite of TclChannelPreserve in Tcl_RegisterChannel */
    TclChannelRelease(chan);
    statePtr->refCount--;

    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995
1996
1997







-
+











-
+







    return (Tcl_Channel) chanPtr;
}

void
TclChannelPreserve(
    Tcl_Channel chan)
{
    ((Channel *)chan)->refCount++;
    TclAtomicFetchInc(&((Channel *)chan)->refCount);
}

void
TclChannelRelease(
    Tcl_Channel chan)
{
    Channel *chanPtr = (Channel *) chan;

    if (chanPtr->refCount == 0) {
	Tcl_Panic("Channel released more than preserved");
    }
    if (--chanPtr->refCount) {
    if (TclAtomicFetchDec(&chanPtr->refCount)) {
	return;
    }
    if (chanPtr->typePtr == NULL) {
	ckfree(chanPtr);
    }
}

3195
3196
3197
3198
3199
3200
3201






3202
3203
3204
3205
3206
3207
3208
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224







+
+
+
+
+
+







    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState *prevCSPtr;	/* Preceding channel state in list of all
				 * states - used to splice a channel out of
				 * the list on close. */
    ChannelState *statePtr = chanPtr->state;
				/* State of the channel stack. */

    /*
     * Firstly notify any - channel has no owner threads anymore.
     */

    statePtr->managingThread = NULL;

    /*
     * Remove this channel from of the list of all channels (in the current
     * thread).
     */

    if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) {
	tsdPtr->firstCSPtr = statePtr->nextCSPtr;
8701
8702
8703
8704
8705
8706
8707














8708
8709
8710
8711
8712
8713
8714
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744







+
+
+
+
+
+
+
+
+
+
+
+
+
+







    for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) {
	statePtr->interestMask |= chPtr->mask;
    }

    UpdateInterest(statePtr->topChanPtr);
}

static void
SafeFreeScriptRecord(
    EventScriptRecord *esPtr)
{
    /* if not executed - remove it right now */
    if (esPtr->execDepth == 0) {
	TclDecrRefCount(esPtr->scriptPtr);
	ckfree(esPtr);
    } else if (esPtr->execDepth > 0) {
	/* inverse depth to notify event-handlers, they should remove it hereafter */
	esPtr->execDepth = -esPtr->execDepth;
    }
    /* execution in-between and already notified (negative). */
}
/*
 *----------------------------------------------------------------------
 *
 * DeleteScriptRecord --
 *
 *	Delete a script record for this combination of channel, interp and
 *	mask.
8744
8745
8746
8747
8748
8749
8750
8751
8752

8753
8754
8755
8756
8757
8758
8759
8774
8775
8776
8777
8778
8779
8780


8781
8782
8783
8784
8785
8786
8787
8788







-
-
+







		CLANG_ASSERT(prevEsPtr);
		prevEsPtr->nextPtr = esPtr->nextPtr;
	    }

	    Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		    TclChannelEventScriptInvoker, esPtr);

	    TclDecrRefCount(esPtr->scriptPtr);
	    ckfree(esPtr);
	    SafeFreeScriptRecord(esPtr);

	    break;
	}
    }
}

/*
8785
8786
8787
8788
8789
8790
8791
8792

8793
8794
8795
8796
8797
8798
8799
8800
8814
8815
8816
8817
8818
8819
8820

8821

8822
8823
8824
8825
8826
8827
8828







-
+
-







    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    EventScriptRecord *esPtr;
    int makeCH;

    for (esPtr=statePtr->scriptRecordPtr; esPtr!=NULL; esPtr=esPtr->nextPtr) {
	if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
	    TclDecrRefCount(esPtr->scriptPtr);
	    SafeFreeScriptRecord(esPtr);
	    esPtr->scriptPtr = NULL;
	    break;
	}
    }

    makeCH = (esPtr == NULL);

    if (makeCH) {
8810
8811
8812
8813
8814
8815
8816

8817
8818
8819
8820
8821
8822
8823
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852







+







     */

    esPtr->chanPtr = chanPtr;
    esPtr->interp = interp;
    esPtr->mask = mask;
    Tcl_IncrRefCount(scriptPtr);
    esPtr->scriptPtr = scriptPtr;
    esPtr->execDepth = 0;

    if (makeCH) {
	esPtr->nextPtr = statePtr->scriptRecordPtr;
	statePtr->scriptRecordPtr = esPtr;

	Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
		TclChannelEventScriptInvoker, esPtr);
8852
8853
8854
8855
8856
8857
8858







8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869


8870













8871
8872
8873
8874
8875
8876
8877
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928







+
+
+
+
+
+
+











+
+

+
+
+
+
+
+
+
+
+
+
+
+
+







				 * registered. */
    EventScriptRecord *esPtr;	/* The event script + interpreter to eval it
				 * in. */
    int result;			/* Result of call to eval script. */

    esPtr = clientData;
    chanPtr = esPtr->chanPtr;

    if ( esPtr->scriptPtr == NULL || esPtr->execDepth < 0 
      || Tcl_GetCurrentThread() != chanPtr->state->managingThread
    ) {
	return;
    }

    mask = esPtr->mask;
    interp = esPtr->interp;

    /*
     * We must preserve the interpreter so we can report errors on it later.
     * Note that we do not need to preserve the channel because that is done
     * by Tcl_NotifyChannel before calling channel handlers.
     */

    Tcl_Preserve(interp);
    TclChannelPreserve((Tcl_Channel)chanPtr);

    esPtr->execDepth++;
    result = Tcl_EvalObjEx(interp, esPtr->scriptPtr, TCL_EVAL_GLOBAL);

    if (esPtr->execDepth > 0) {
	--esPtr->execDepth;
    } else if (esPtr->execDepth < 0) {
	/* 
	 * Negative depth meants - the handler was removed, so we should increase,
	 * and remove esPtr record by the last handler (if it reached 0).
	 */
	if (++esPtr->execDepth == 0) {
	    SafeFreeScriptRecord(esPtr);
	    /* don't use esPtr at here. */
	}
    }

    /*
     * On error, cause a background error and remove the channel handler and
     * the script record.
     *
     * NOTE: Must delete channel handler before causing the background error
     * because the background error may want to reinstall the handler.
Changes to generic/tclIO.h.
79
80
81
82
83
84
85


86
87
88
89
90
91
92
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94







+
+







				 * delete the handler. */
    Tcl_Obj *scriptPtr;		/* Script to invoke. */
    Tcl_Interp *interp;		/* In what interpreter to invoke script? */
    int mask;			/* Events must overlap current mask for the
				 * stored script to be invoked. */
    struct EventScriptRecord *nextPtr;
				/* Next in chain of records. */
    int execDepth;		/* Execution depth inside the event-handlers,
				 * if negative it should be removed as 0 reached. */
} EventScriptRecord;

/*
 * struct Channel:
 *
 * One of these structures is allocated for each open channel. It contains
 * data specific to the channel but which belongs to the generic part of the
109
110
111
112
113
114
115
116




117
118
119
120
121
122
123
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128







-
+
+
+
+







     * Intermediate buffers to hold pre-read data for consumption by a newly
     * stacked transformation. See 'Tcl_StackChannel'.
     */

    ChannelBuffer *inQueueHead;	/* Points at first buffer in input queue. */
    ChannelBuffer *inQueueTail;	/* Points at last buffer in input queue. */

    int refCount;
    TclAtomicInt refCount;	/* Reference counter, volatile forces atomic
				 * direct incr/decr during transfer process,
				 * if temorary shared between threads (avoids
				 * unexpected compiler optimization) */
} Channel;

/*
 * struct ChannelState:
 *
 * One of these structures is allocated for each open channel. It contains
 * data specific to the channel but which belongs to the generic part of the
Changes to generic/tclInt.h.
119
120
121
122
123
124
125




























126
127
128
129
130
131
132
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#   endif
#endif

#if defined(_WIN32) && defined(_MSC_VER)
#   define vsnprintf _vsnprintf
#endif

/*
 * Interlocked (atomic fetch) primitives.
 *
 * Note gcc > 4.1 (also for mingw) has native support for builtin atomic operations.
 * ToDo: extend with support for atomic_ops, Darwin atomic, Sun atomics if available.
 */
#if !defined(__WIN32__) || defined(__GNUC__) || defined(__MINGW32__) /* UNIX or GCC */
#  define TclAtomicInt			long volatile

#  define TclAtomicFetchAdd(p, add) \
		__sync_fetch_and_add((p), (add))
#  define TclAtomicFetchSub(p, sub) \
		__sync_fetch_and_sub((p), (sub))
#  define TclAtomicFetchInc(p)	\
		(__sync_add_and_fetch((p), 1))
#  define TclAtomicFetchDec(p)	\
		(__sync_sub_and_fetch((p), 1))
#else  /* defined(__WIN32__) */
#  define TclAtomicInt			LONG volatile
#  define TclAtomicFetchAdd(p, add) \
		InterlockedExchangeAdd((LONG volatile *)(p), (add))
#  define TclAtomicFetchSub(p, sub) \
		InterlockedExchangeSubtract((LONG volatile *)(p), (sub))
#  define TclAtomicFetchInc(p)	\
		InterlockedIncrement((LONG volatile *)(p))
#  define TclAtomicFetchDec(p)	\
		InterlockedDecrement((LONG volatile *)(p))
#endif /* defined(__WIN32__) */
/*
 * The following procedures allow namespaces to be customized to support
 * special name resolution rules for commands/variables.
 */

struct Tcl_ResolvedVarInfo;