From 377e7c77456825d7dc9d44f44c937ff57e1bfce3 Mon Sep 17 00:00:00 2001 From: ferrieux Date: Thu, 18 Aug 2011 15:06:58 +0000 Subject: [Bug 3096275] Sync fcopy buffers input. --- ChangeLog | 4 ++++ generic/tclIO.c | 15 ++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64a25dd..e294229 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-18 Alexandre Ferrieux + + * generic/tclIO.c [Bug 3096275] Sync fcopy buffers input. + 2011-08-18 Jan Nijtmans * generic/tclUniData.c: [Bug 3393714] overflow in toupper delta diff --git a/generic/tclIO.c b/generic/tclIO.c index a19fde8..95afd63 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -79,7 +79,7 @@ static int DetachChannel(Tcl_Interp *interp, Tcl_Channel chan); static void DiscardInputQueued(ChannelState *statePtr, int discardSavedBuffers); static void DiscardOutputQueued(ChannelState *chanPtr); -static int DoRead(Channel *chanPtr, char *srcPtr, int slen); +static int DoRead(Channel *chanPtr, char *srcPtr, int slen, int allowShortReads); static int DoWrite(Channel *chanPtr, const char *src, int srcLen); static int DoReadChars(Channel *chan, Tcl_Obj *objPtr, int toRead, int appendFlag); @@ -5444,7 +5444,7 @@ Tcl_Read( return -1; } - return DoRead(chanPtr, dst, bytesToRead); + return DoRead(chanPtr, dst, bytesToRead, 0); } /* @@ -9169,7 +9169,8 @@ CopyData( } if (inBinary || sameEncoding) { - size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb); + size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb, + !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, 0 /* No append */); @@ -9408,7 +9409,8 @@ static int DoRead( Channel *chanPtr, /* The channel from which to read. */ char *bufPtr, /* Where to store input read. */ - int toRead) /* Maximum number of bytes to read. */ + int toRead, /* Maximum number of bytes to read. */ + int allowShortReads) /* Allow half-blocking (pipes,sockets) */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ @@ -9449,7 +9451,10 @@ DoRead( } goto done; } - } + } else if (allowShortReads) { + copied += copiedNow; + break; + } } ResetFlag(statePtr, CHANNEL_BLOCKED); -- cgit v0.12 From 72fa03ae4fe97ce840005caa68f3467a1489260a Mon Sep 17 00:00:00 2001 From: ferrieux Date: Fri, 19 Aug 2011 13:59:57 +0000 Subject: [Bug 2981154] async-4.3 segfault. --- ChangeLog | 8 ++++++-- generic/tclTest.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e294229..d8cf76e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ +2011-08-19 Alexandre Ferrieux + + * generic/tclTest.c: [Bug 2981154] async-4.3 segfault. + 2011-08-18 Alexandre Ferrieux - * generic/tclIO.c [Bug 3096275] Sync fcopy buffers input. + * generic/tclIO.c: [Bug 3096275] Sync fcopy buffers input. 2011-08-18 Jan Nijtmans @@ -16,7 +20,7 @@ 2011-08-17 Alexandre Ferrieux * doc/interp.n: Document TIP 378's one-way-ness. - + 2011-08-17 Don Porter * generic/tclGet.c: [Bug 3393150] Overlooked free of intreps. diff --git a/generic/tclTest.c b/generic/tclTest.c index bac0c7f..3e3bc09 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -75,6 +75,8 @@ typedef struct TestAsyncHandler { /* Next is list of handlers. */ } TestAsyncHandler; +TCL_DECLARE_MUTEX(asyncTestMutex); + static TestAsyncHandler *firstHandler = NULL; /* @@ -791,17 +793,20 @@ TestasyncCmd( goto wrongNumArgs; } asyncPtr = ckalloc(sizeof(TestAsyncHandler)); + asyncPtr->command = ckalloc(strlen(argv[2]) + 1); + strcpy(asyncPtr->command, argv[2]); + Tcl_MutexLock(&asyncTestMutex); asyncPtr->id = nextId; nextId++; asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, - (ClientData) asyncPtr); - asyncPtr->command = ckalloc(strlen(argv[2]) + 1); - strcpy(asyncPtr->command, argv[2]); + (ClientData) asyncPtr->id); asyncPtr->nextPtr = firstHandler; firstHandler = asyncPtr; + Tcl_MutexUnlock(&asyncTestMutex); Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id)); } else if (strcmp(argv[1], "delete") == 0) { if (argc == 2) { + Tcl_MutexLock(&asyncTestMutex); while (firstHandler != NULL) { asyncPtr = firstHandler; firstHandler = asyncPtr->nextPtr; @@ -809,6 +814,7 @@ TestasyncCmd( ckfree(asyncPtr->command); ckfree(asyncPtr); } + Tcl_MutexUnlock(&asyncTestMutex); return TCL_OK; } if (argc != 3) { @@ -817,6 +823,7 @@ TestasyncCmd( if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } + Tcl_MutexLock(&asyncTestMutex); for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL; prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id != id) { @@ -832,6 +839,7 @@ TestasyncCmd( ckfree(asyncPtr); break; } + Tcl_MutexUnlock(&asyncTestMutex); } else if (strcmp(argv[1], "mark") == 0) { if (argc != 5) { goto wrongNumArgs; @@ -862,7 +870,7 @@ TestasyncCmd( if (asyncPtr->id == id) { Tcl_ThreadId threadID; if (Tcl_CreateThread(&threadID, AsyncThreadProc, - (ClientData) asyncPtr, TCL_THREAD_STACK_DEFAULT, + (ClientData) id, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { Tcl_SetResult(interp, "can't create thread", TCL_STATIC); return TCL_ERROR; @@ -886,15 +894,29 @@ TestasyncCmd( static int AsyncHandlerProc( - ClientData clientData, /* Pointer to TestAsyncHandler structure. */ + ClientData clientData, /* If of TestAsyncHandler structure. + * in global list. */ Tcl_Interp *interp, /* Interpreter in which command was * executed, or NULL. */ int code) /* Current return code from command. */ { - TestAsyncHandler *asyncPtr = (TestAsyncHandler *) clientData; + TestAsyncHandler *asyncPtr; + int id = (int) clientData; const char *listArgv[4], *cmd; char string[TCL_INTEGER_SPACE]; + Tcl_MutexLock(&asyncTestMutex); + for (asyncPtr = firstHandler; asyncPtr != NULL; + asyncPtr = asyncPtr->nextPtr) { + if (asyncPtr->id == id) break; + } + Tcl_MutexUnlock(&asyncTestMutex); + + if (!asyncPtr) { + /* Woops - this one was deleted between the AsyncMark and now */ + return TCL_OK; + } + TclFormatInt(string, code); listArgv[0] = asyncPtr->command; listArgv[1] = Tcl_GetString(Tcl_GetObjResult(interp)); @@ -932,12 +954,22 @@ AsyncHandlerProc( #ifdef TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc( - ClientData clientData) /* Parameter is a pointer to a + ClientData clientData) /* Parameter is the id of a * TestAsyncHandler, defined above. */ { - TestAsyncHandler *asyncPtr = clientData; + TestAsyncHandler *asyncPtr; + int id = (int) clientData; + Tcl_Sleep(1); - Tcl_AsyncMark(asyncPtr->handler); + Tcl_MutexLock(&asyncTestMutex); + for (asyncPtr = firstHandler; asyncPtr != NULL; + asyncPtr = asyncPtr->nextPtr) { + if (asyncPtr->id == id) { + Tcl_AsyncMark(asyncPtr->handler); + break; + } + } + Tcl_MutexUnlock(&asyncTestMutex); Tcl_ExitThread(TCL_OK); TCL_THREAD_CREATE_RETURN; } @@ -7054,5 +7086,7 @@ TestconcatobjCmd( * mode: c * c-basic-offset: 4 * fill-column: 78 + * tab-width: 8 + * indent-tabs-mode: nil * End: */ -- cgit v0.12 From a6827503fbf6b31c4d417b8842f67144cd792778 Mon Sep 17 00:00:00 2001 From: ferrieux Date: Fri, 19 Aug 2011 14:23:19 +0000 Subject: [Bug 1774689] async-4.3 sometimes fails. --- ChangeLog | 1 + tests/async.test | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d8cf76e..c998c27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2011-08-19 Alexandre Ferrieux * generic/tclTest.c: [Bug 2981154] async-4.3 segfault. + * tests/async.test: [Bug 1774689] async-4.3 sometimes fails. 2011-08-18 Alexandre Ferrieux diff --git a/tests/async.test b/tests/async.test index db21333..7834ed5 100644 --- a/tests/async.test +++ b/tests/async.test @@ -196,7 +196,7 @@ test async-4.3 {async interrupting loop-less bytecode sequence} -constraints { set aresult {Async event not delivered} testasync marklater $handle set i 0 - } [string repeat {;incr i;} 1500000] { + } "[string repeat {;incr i;} 1500000]after 10;" { return $aresult }]] $hm } -result {test pattern} -cleanup { -- cgit v0.12 From c7308459febcf0a9d4fd00a1522a33b0fe6fa74b Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 19 Aug 2011 16:05:46 +0000 Subject: Preserve the chanPtr during FlushChannel so that channel drivers don't yank it away before we're done with it. --- ChangeLog | 5 +++++ generic/tclIO.c | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c998c27..8cbc045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-19 Don Porter + + * generic/tclIO.c: Preserve the chanPtr during FlushChannel so that + channel drivers don't yank it away before we're done with it. + 2011-08-19 Alexandre Ferrieux * generic/tclTest.c: [Bug 2981154] async-4.3 segfault. diff --git a/generic/tclIO.c b/generic/tclIO.c index 95afd63..946b53a 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -2356,6 +2356,7 @@ FlushChannel( * of the queued output to the channel. */ + Tcl_Preserve(chanPtr); while (1) { /* * If the queue is empty and there is a ready current buffer, OR if @@ -2385,7 +2386,8 @@ FlushChannel( */ if (!calledFromAsyncFlush && GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { - return 0; + errorCode = 0; + goto done; } /* @@ -2532,7 +2534,7 @@ FlushChannel( if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { if (wroteSome) { - return errorCode; + goto done; } else if (statePtr->outQueueHead == NULL) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); ChanWatch(chanPtr, statePtr->interestMask); @@ -2549,7 +2551,8 @@ FlushChannel( (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { - return CloseChannel(interp, chanPtr, errorCode); + errorCode = CloseChannel(interp, chanPtr, errorCode); + goto done; } /* @@ -2562,8 +2565,12 @@ FlushChannel( (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { - return CloseChannelPart(interp, chanPtr, errorCode, TCL_CLOSE_WRITE); + errorCode = CloseChannelPart(interp, chanPtr, errorCode, TCL_CLOSE_WRITE); + goto done; } + + done: + Tcl_Release(chanPtr); return errorCode; } -- cgit v0.12 From b4307ec076f504b43a12901bb34c646ea5267391 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 19 Aug 2011 19:07:17 +0000 Subject: 3394654, 3393276 Revise FlushChannel() to account for the possibility that the ChanWrite() call might recycle the buffer out from under us. --- ChangeLog | 4 ++++ generic/tclIO.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8cbc045..db4bf84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-08-19 Don Porter + * generic/tclIO.c: [Bugs 3394654, 3393276] Revise FlushChannel() to + account for the possibility that the ChanWrite() call might recycle + the buffer out from under us. + * generic/tclIO.c: Preserve the chanPtr during FlushChannel so that channel drivers don't yank it away before we're done with it. diff --git a/generic/tclIO.c b/generic/tclIO.c index 946b53a..ae1b89a 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -2510,7 +2510,9 @@ FlushChannel( wroteSome = 1; } - bufPtr->nextRemoved += written; + if (!IsBufferEmpty(bufPtr)) { + bufPtr->nextRemoved += written; + } /* * If this buffer is now empty, recycle it. -- cgit v0.12 From 6b86c2f514ad7c263691443055ad1d0a94a9f4f9 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 19 Aug 2011 20:27:48 +0000 Subject: 3393279, 3393280 ReflectClose(.) is missing Tcl_EventuallyFree() calls at some of its exits. --- ChangeLog | 3 +++ generic/tclIORTrans.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index db4bf84..5e7821a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-08-19 Don Porter + * generic/tclIORTrans.c: [Bugs 3393279, 3393280] ReflectClose(.) is + missing Tcl_EventuallyFree() calls at some of its exits. + * generic/tclIO.c: [Bugs 3394654, 3393276] Revise FlushChannel() to account for the possibility that the ChanWrite() call might recycle the buffer out from under us. diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index 272306b..4806690 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -940,6 +940,7 @@ ReflectClose( int errorCode; if (!TransformDrain(rtPtr, &errorCode)) { + Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return errorCode; } } @@ -948,6 +949,7 @@ ReflectClose( int errorCode; if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) { + Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return errorCode; } } -- cgit v0.12