#2 error handling with bgerror in Tk

obsolete: 8.3.2
closed-fixed
69. Events (88)
7
2002-07-25
2000-10-26
Anonymous
No

OriginalBugID: 3998 Bug
Version: 8.2.3
SubmitDate: '2000-01-10'
LastModified: '2000-01-23'
Severity: MED
Status: Assigned
Submitter: techsupp
ChangedBy: hobbs
RelatedBugIDs: 2577 2136 750
OS: All
FixedDate: '2000-10-25'
ClosedDate: '2000-10-25'

Name:
Torsten Rottmann

ReproducibleScript:
wish
% after 1 dfdf
after#0
% bgerror failed to handle background error.
Original error: invalid command name "dfdf"
Error in bgerror: invoked "break" outside of a loop

ObservedBehavior:
If you press "Skip Messages" ( the "return -code break" behaviour) former version of Tcl
didn't complain about "break outside a loop"

DesiredBehavior:
Same as in Tcl8.0: nothing

This behavior seems to have changed between 8.0.4 and 8.1.
-- 01/23/2000 hobbs

Discussion

  • Donal K. Fellows

    Still there in 8.3.2 in wish, but *not* tclsh of the same vintage with the following script:

    proc bgerror {msg} {puts "BGERROR: $msg"; return -code break}
    after 1 notacommand
    vwait forever

    Something bizarre is going on here; moving this bug to Tk...

     
  • Donal K. Fellows

    • priority: 5 --> 7
    • milestone: 102432 --> 100100
     
  • Don Porter

    Don Porter - 2000-11-29
    • labels: 100100 --> 69. Events
    • milestone: 100100 --> obsolete: 8.3.2
     
  • Don Porter

    Don Porter - 2000-11-29

    See also bug 122014

     
  • Donal K. Fellows

    Investigated further. Behaviour is different between:
    after 1 foo; after 1 bar; after 1000 set x 1; vwait x
    and
    after 1 foo; after 1 bar
    The second behaviour is also duplicated by
    after 1 foo; after 1 bar; update
    but the first behaviour is duplicated by
    after 1 foo; after 1 bar; after 5; update

    Problem is directly caused by an erroneous call to ProcessProcResultCode() (in tcl/generic/tclProc.c) but I've not tracked down yet what is triggering that. I suspect it might be due to events that are handled during the event handler not being treated as candidates for removal. In some way. Yuck.

     
  • Joe English

    Joe English - 2002-06-22
    • assigned_to: nobody --> jenglish
     
  • Joe English

    Joe English - 2002-07-06

    Logged In: YES
    user_id=68433

    Still present in 8.4b1, as the following test script
    demonstrates:

    # Run in tclsh8.4
    #
    proc bgerror {error} {
    puts stderr "Background error: $error\n$::errorInfo"
    return -code break
    }
    after idle error a ; after idle error b ; after idle error c
    update idletasks
    # Does the right thing -- prints "Background error: a\n...",
    then stops.

    package require Tk ;# This works now. Neat!
    after idle error a ; after idle error b ; after idle error c
    # Does the wrong thing -- prints "Backround error: a\n...",
    # then complains that "bgerror failed to handle background
    error"
    # " [...] Error in bgerror: invoked "break" outside of a
    loop"

    dkf is right, this is definitely caused by an erroneous call
    to ProcessProcResultCode.

     
  • Don Porter

    Don Porter - 2002-07-06

    Logged In: YES
    user_id=80530

    This may be TIP 90 related; I'll take a look.

     
  • Don Porter

    Don Porter - 2002-07-06
    • assigned_to: jenglish --> dgp
     
  • Joe English

    Joe English - 2002-07-06
    • assigned_to: dgp --> jenglish
     
  • Joe English

    Joe English - 2002-07-06

    Logged In: YES
    user_id=68433

    Another data point: In wish, the following does the Right
    Thing:

    package require Tk
    proc bgerror {error} { # as below
    puts stderr "bgerror: $error" ; return -code break
    }
    after idle error a ; after idle error b ; after idle error c
    ; update idletasks

    The difference seems to be whether HandleBgErrors is called
    from the main event loop or from inside an [update] call.
    This might help track this down.

     
  • Joe English

    Joe English - 2002-07-07

    Logged In: YES
    user_id=68433

    OK, here's the scoop:

    The difference between
    after idle error foo; update
    and
    after idle error
    typed at the '%' prompt in wish, is that in the
    first case HandleBgErrors ends up getting called
    with interp->numLevels == 1 and in the second case
    it's called with interp->numLevels == 0.

    Eventually, TclObjInterpProc() is called to
    process the body of 'proc bgerror', which in
    turn calls Tcl_EvalObjEx().

    Tcl_EvalObjEx() has code that replicates the
    functionality of ProcessProcResultCode(), to wit:
    call TclUpdateReturnInfo() to change e.g. [return
    -code break] into TCL_BREAK. This code path
    is only taken if interp->numLevels == 0.
    (Tcl_EvalObjEx() then checks for unexpected
    TCL_BREAK or TCL_CONTINUE results and turns those
    into TCL_ERRORs, but only if !(interp->evalFlags
    & TCL_ALLOW_EXCEPTIONS); in this case that flag
    has been set by HandleBgErrors, so that part
    is skipped).

    Back to TclObjInterpProc(). At this point
    TCL_RETURN has already been changed to
    TCL_BREAK, which ProcessProcResultCode() turns
    into TCL_ERROR, which eventually gets back to
    HandleBgError().

    Summarizing: if background errors are processed when
    interp->numLevels == 0, the ProcessProcResult()'s job
    gets done twice.

    Possible fixes:

    (1) Tcl_EvalObjEx() shouldn't be making the
    decision about what to do with exceptional return
    codes (TCL_RETURN, TCL_BREAK, and TCL_CONTINUE);
    it's not documented to do so. Removing this
    section of the code would break lots of stuff
    though.

    (2) TclObjInterpProc() could increment and
    decrement interp->numLevels around the call
    to Tcl_EvalObjEx(). This would work around
    this particular problem, and it might even be
    the correct thing to do in any case, but the
    consequences might be far-reaching. I don't
    know who else uses interp->numLevels or what
    its expected meaning is.

    (3) TclObjInterpProc() could be modified to call
    TclCompEvalObj(interp, proc->bodyPtr) instead of
    Tcl_EvalObjEx(interp, proc->bodyPtr, 0).
    (TclCompEvalObj() is the workhorse routine that
    Tcl_EvalObjEx() ends up calling when invoked from
    TclObjInterpProc()).

    I've implemented #3, and the test suite still passes.
    Passing this on to Jeff for final resolution.

     
  • Joe English

    Joe English - 2002-07-07
    • assigned_to: jenglish --> hobbs
     
  • Joe English

    Joe English - 2002-07-08

    Patch to generic/tclProc.c r1.37

     
  • Joe English

    Joe English - 2002-07-09

    Logged In: YES
    user_id=68433

    Followup: possibly #1 (don't do TclUpdateReturnInfo() etc.
    in Tcl_EvalObjEx()) is the right fix after all. This bit is
    replicated in several other places in the core.

    Tcl Bug #480896 may also be related.

    Reassigning to dgp, who is already on top of this issue.

     
  • Joe English

    Joe English - 2002-07-09
    • assigned_to: hobbs --> dgp
     
  • Joe English

    Joe English - 2002-07-25
    • status: open --> closed-fixed
     
  • Joe English

    Joe English - 2002-07-25

    Logged In: YES
    user_id=68433

    Miguel Sofer confirmed (on the chat) that #3 should be
    done. Committing tclProc.c.patch.

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks