Tcl Source Code

View Ticket
Login
Ticket UUID: 88aef05cda36aca8233aaeaa1d8b41cb4b188192
Title: Script level application bug in refchan causes Tcl crash
Type: Bug Version: 8.5.15
Submitter: anonymous Created on: 2013-09-30 03:25:53
Subsystem: 25. Channel System Assigned To: dgp
Priority: 7 High Severity: Important
Status: Closed Last Modified: 2014-04-15 17:26:23
Resolution: Fixed Closed By: dgp
    Closed on: 2014-04-15 17:26:23
Description:
The following code causes the Tcl interpreter to crash. Note the code is buggy (recursively enters the blocking proc via chan configure. But should not cause an interpreter crash.

namespace eval demo {}
proc demo::initialize {chan mode} {
    return {initialize finalize watch blocking read write configure cget cgetall}
}

proc demo::finalize {chan} {
}

proc demo::blocking {chan mode} {
    chan configure $chan -blocking $mode
    return
}


namespace eval demo {
    namespace export initialize finalize blocking 
    namespace ensemble create
}

set ch [chan create {read write} demo]
chan configure $ch -blocking 0

-> crash
User Comments: dgp added on 2014-04-15 17:26:23:
fix merged to trunk.

dgp added on 2014-04-15 16:11:53:
Fix committed to 8.5 branch.

Additional cleanup and improvements pending.

aku added on 2014-04-02 16:17:48:
> This is presumably so that the cost of allocating
> a new eval array doesn't have to be paid each time.

I am very sure that this is what is was thinking at the time.

> can only be InvokeTclMethod() call operating on each
> reflected channel at a time.

Yes. Also something I was definitely _not_ seeing when writing the code.

So, possible solutions ...

(1) Dynamically (de)allocate the damn array in each call of InvokeTclMethod()
(2) Flatly forbid the recursive entry of InvokeTclMethod().

In terms of implementation both possibilities seem to be equivalent in difficulty, i.e. while not trivial, at least easy.

In light of other data structures needing to be preserved for such calls, as demonstrated by related bug reports I currently trend towards preferring (2).

dgp added on 2014-04-02 02:40:10:
This one is pretty ugly.

The problem arises because the reflected
channel builds the command to be evaluated
in an array within the reflected channel
data structure, rcPtr->argv .  This is presumably
so that the cost of allocating a new eval array
doesn't have to be paid each time.

The problem is if there is one argv array per
reflected channel, then there can only be one
InvokeTclMethod() call operating on each
reflected channel at a time.  As soon as you 
try to do two concurrently -- such as when 
one nests in the other -- they will stomp on
each other's argument words, and crashing is
about the nicest thing to expect.

aku added on 2013-10-17 16:20:44:
Most likely some data structure not getting properly preserved and/or locked against bad re-entrance.

Likely also in the 8.6 branch, and novem

dgp added on 2013-09-30 15:19:40:
Confirmed the segfault.

Also crashes in 8.5.15 and 8.5.0, so
this is not a recent regression.

Passing on to the refchan maintainer for
a deeper look.