Tcl Source Code

View Ticket
Login
Ticket UUID: 8f559999fa000614504de7a7eefbc99dc7beea2b
Title: background error swallowed with command delete trace on a coroutine
Type: Bug Version: head
Submitter: pooryorick Created on: 2017-06-22 17:11:10
Subsystem: 20. [interp] Assigned To: nobody
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2017-06-23 08:12:13
Resolution: Invalid Closed By: sebres
    Closed on: 2017-06-23 08:12:13
Description:

When an error occurs in a coroutine that has a delete trace set on it, the delete trace is invoked before the background error handler is invoked. When a coroutine is acting as the main routine in a script it may then carry out the remainder of the program, oblivious to the error:

proc bgerror {error options} {
    puts stderr [dict get $options -errorinfo]
    exit 1
}

proc p1 {} {
    yield [info coroutine]
    error {never gonna give you up}
}

coroutine main ::apply [list {} {
    yield [info coroutine]
    coroutine c1 p1
    trace add command c1 delete [info coroutine]
    yieldto c1
    exit 0
} [namespace current]]
after idle main
interp bgerror {} [namespace which bgerror]
vwait forever

User Comments: sebres added on 2017-06-23 08:12:13:

I realized that your tracing initialization is wrong here - command executed from trace expects specified arguments.

If you rewrite your code like:

proc bgerror {error options} {
    puts stderr [dict get $options -errorinfo]
    puts stderr *************exit-1
    exit 1
}

proc p1 {} {
    yield [info coroutine]
    puts *************produce-error
    error {never gonna give you up}
}

proc trace-c1 {args} {
    puts *************in-trace--$args
}

coroutine main ::apply [list {} {
    yield [info coroutine]
    coroutine c1 p1
    # wrong trace:
    # trace add command c1 delete [info coroutine]
    trace add command c1 delete [list trace-c1 [info coroutine]]
    yieldto c1
    puts stderr *************exit-0
    exit 0
} [namespace current]]

after idle main
interp bgerror {} [namespace which bgerror]
vwait forever

You'll then see:

*************produce-error
*************in-trace--::main ::c1 {} delete
never gonna give you up
    while executing
"error {never gonna give you up}"
    (procedure "p1" line 4)
    invoked from within
"p1"
    invoked from within
"c1"
    invoked from within
"main"
    ("after" script)
*************exit-1

Thus I close this as invalid. Please reopen if I'm wrong.


sebres added on 2017-06-22 20:00:20:
Please note that bgerror is an idle-event (with newest generation-value).
It comparable with (after idle bgerror ...).
In this case, it will be definitelly executed in the next event-cycle.
But the trace will be executed still inside the same cycle (within processing of the last event).

To do it in other order:
- rather don't use bgerror handling.
- or rewrite your trace also using "after idle".

So works as expected, thus I'll recommend to close the ticket.