Tcl Source Code

View Ticket
Login
Ticket UUID: 67a5eabbd3d195915d3ccc13246bdecf10e20726
Title: refchan, coroutine, and postevent from the "watch" proc
Type: Bug Version: 8.6.6
Submitter: pooryorick Created on: 2016-08-15 10:31:45
Subsystem: 60. NRE and coroutines Assigned To: pooryorick
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2021-06-20 05:15:04
Resolution: Fixed Closed By: pooryorick
    Closed on: 2021-06-20 05:15:04
Description: (text/x-fossil-wiki)
The following script results in an error to the effect that the coroutine is
already running.

<code><verbatim>
#! /bin/env tclsh

interp bgerror {} [list apply {{res opts} {
    puts stderr [dict get $opts -errorinfo]
    exit 1
}}]

namespace eval schan {
    namespace ensemble create
    namespace export *
    proc open {} {
        variable chans
        set chan [chan create read [namespace current]]

    }
    proc initialize {chan mode} {
        return [list initialize finalize read watch]
    }

    proc read {chan count} {
    }

    proc watch {chan eventspec} {
        chan postevent $chan $eventspec
    }
}

coroutine c1 apply [list {} {
    set chan [schan::open]
    chan event $chan readable [list [info coroutine]]
    yield
    puts thiswillnotappear
}] 
vwait ::forever
</verbatim></code>
User Comments: pooryorick added on 2021-06-16 21:24:47: (text/x-fossil-wiki)
Yes, that's an accurate summary, as the call to Tcl_NotifyChannel is moved into a timer event handler.

dgp added on 2021-06-16 17:15:04:
Can the patch be described accurately as changing to operations
of the [chan postevent] command from synchronous to asynchronous?

jan.nijtmans added on 2021-06-15 14:58:25: (text/x-fossil-wiki)
Backed out because of [18f4a94d03]. Therefore re-opening this one.

pooryorick added on 2019-04-23 13:02:56: (text/x-fossil-wiki)
Fixed in [e066e24f36f67a8d] by using <code>Tcl_CreateTimerHandler()</code> to
schedule the call to <code>Tcl_NotifyChannel()</code>.

ferrieux added on 2016-09-06 23:43:17:
FWIW, some time ago, async fcopy suffered from a similar "premature callback" issue: in some circumstances, where the copy was provably complete, the completion callback fired from within fcopy instead of from the event loop  (despite the async flag).

It was Obviously Wrong, and fixed. I'm tempted to follow your suggestion and propose the same here, though I don't know the details of the refchan enough to be sure of the analogy.

Maybe Andreas could chime in.

pooryorick added on 2016-09-06 20:36:03: (text/x-fossil-wiki)
This happens because <code>chan postevent</code> calls <code>Tcl_NotifyChannel()</code> instead of scheduling an event, as explained in [http://core.tcl.tk/tcl/tktview/ef28eb1f15167156c898|ef28eb1f15167156c898].

ferrieux added on 2016-08-15 12:03:52:
Hum, never mind, simple interp bgerror playing its role, sorry.

ferrieux added on 2016-08-15 11:58:39:
Interesting: it's not even a vanilla error, it's uncatchable !
It sorta reaches the default "spit out errorInfo and exit(1)", regardless of any [catch] range.
Digging...

aspect added on 2016-08-15 11:53:46:
The stack trace of the error is:
 c1
  chan event
   schan::watch
    c1 (boom!)

ie, yield is not even reached.

schan::watch should not immediately call [chan postevent].  Wrapping that in [after 0] removes the crash, but I'm not sure this is correct behaviour for postevent either.

See tcllib or http://chiselapp.com/user/aspect/repository/tcl-hacks/artifact/6cb89e9c9ebb6800 for other strategies (but I now see potentially a similar bug in the chiselapp link ..)