TIP:            221
Title:          Allow Background Error Handlers to Accept Return Options
Version:        $Revision: 2.10 $
Author:         Don Porter <dgp@users.sf.net>
State:          Final
Type:           Project
Vote:           Done
Created:        15-Sep-2004
Post-History:   
Keywords:       bgerror,return,options
Tcl-Version:    8.5

~ Abstract

This TIP proposes a new system for registering a background error
handler of an interp so that the full set of return options ([90]) can
be passed to it.

~ Background

Whenever a script is evaluated as part of handling an event, and
that script evaluation returns TCL_ERROR or some other non-TCL_OK
return code it is not equipped to handle, then the code that
evaluates that script is expected to call ''Tcl_BackgroundError''
to report the exceptional code to the application.

Then ''Tcl_BackgroundError'' will arrange for the command
'''bgerror''' to be called during an idle event.  It is intended
that each application will define a '''::bgerror''' command to its
liking so that background errors are reported (or ignored) as
the application prefers.

The defined syntax for '''bgerror''' is 

 > '''bgerror''' ''message''

The '''bgerror''' command receives as its only argument a copy of
what the interp result was when ''Tcl_BackgroundError'' was called.
This is presumably an error message.

When '''bgerror''' is called, it is also arranged that the
variables '''::errorInfo''' and '''::errorCode''' are set to
the same values they had when ''Tcl_BackgroundError'' was called.
This is effectively another set of arguments passed through a
side channel.

Note that the non-TCL_OK return code that triggered
the ''Tcl_BackgroundError'' call is not itself made known to 
'''bgerror'''.  Nor is the ''-level'', ''-errorline'', or other
return option information made possible by [90] passed along
to '''bgerror''' in any way.

~ Proposal

A new subcommand, '''interp bgerror''' will be created that
allows for registration of a handler command to react to
background errors.  Its syntax will be:

 > '''interp bgerror''' ''path'' ?''cmdPrefix''?

Here ''path'' is the path of an interp, interpreted the same way
as the ''path'' argument to the existing '''interp aliases'''
subcommand.  This argument determines which interp's background
error handler we are interested in.  The value of an empty list
for ''path'' indicates the current interp.

As is the case with other '''interp''' subcommands, an alternative
means to access the same functionality will be made available
as the '''bgerror''' subcommand of the ''slave'' command of
an interp with syntax:

 > ''slave'' '''bgerror''' ?''cmdPrefix''?

When no ''cmdPrefix'' argument is present, the command prefix
currently registered to handle background errors in the ''path''
interp will be returned.  The returned value will be
the ''cmdPrefix'' argument most recently successfully passed
to '''interp bgerror''' ''path'', or the default
background error handler command of the interp.

When a ''cmdPrefix'' argument is present, it must be a valid Tcl
list of length at least one.  An invalid list or an empty list
is an error.  A ''cmdPrefix'' list argument of
length ''N'' will become the first ''N'' substituted words of
the handler command invoked to handle calls to ''Tcl_BackgroundError''.
That is, if the ''cmdPrefix'' argument is stored in a variable
'''cmdPrefix''', subsequent calls to ''Tcl_BackgroundError'' will
lead to evaluation of a command like so:

 > '''{expand}$cmdPrefix''' ''message'' ''returnOptionsDictionary''

The ''message'' argument is the interp result at the time
''Tcl_BackgroundError'' is called.
The ''returnOptionsDictionary'' argument is a Tcl dict value ([111])
holding the value of the interp's return options dictionary at the
time ''Tcl_BackgroundError'' was called.  Specifically,
the ''returnOptionsDictionary'' argument is the value
returned by ''Tcl_GetReturnOptions'' ([227]) at the time
''Tcl_BackgroundError'' is called.

Stored in the ''returnOptionsDictionary'' argument will be values
for the ''-level'' and ''-code'' keys, and when those values
indicate a TCL_ERROR triggered the ''Tcl_BackgroundError'' call,
the ''-errorinfo'', ''-errorcode'', and ''-errorline'' keys will
have values as well.  Any other return options present in the
interp's return options  dictionary at the time ''Tcl_BackgroundError''
is called will also be available in the ''returnOptionsDictionary'' argument.

Note that after this change, applications will be able to
register a background error handling command that has no need
to consult the variables '''::errorInfo''' or '''::errorCode''' at all.

~ Compatibility

Existing applications making use of the '''bgerror''' interface
provide a '''bgerror''' command that expects exactly one argument.

To continue to compatibly support these applications, the default
background error handler command prefix registered in each interp
will be a command that sets the values of '''::errorInfo'''
and '''::errorCode''' to the values of the corresponding keys in
the return options dictionary, if appropriate.  Then it will
invoke the command '''bgerror''' ''message'' in the global namespace.
For complete compatibility, the existing fallbacks will also
be honored in the default handler, including the
invoking a hidden command '''bgerror''' ''message''
in safe interps, and the ultimate fallback (in trusted interps only)
being a message written to the stderr channel of the process as determined
by ''Tcl_GetStdChannel(TCL_STDERR)''.

~ Rejected Alternatives

The first draft of this proposal proposed several attempts to
call '''bgerror''', first with two arguments, then with one.
It was rejected because an error due to calling '''bgerror'''
with the wrong number of arguments could not be distinguished
(easily and reliably) from an error for other reasons.  This
fallback strategy was prone to the masking of errors.

The new proposal is also preferred over the first draft as
it empowers Tcl programmers to leave behind '''bgerror'''
as a ''magic'' command name with special significance to Tcl.
Callback registration is a cleaner mechanism then giving
particular command names privileged status, and we should
move in that direction when the opportunity arises.

An alternative syntax for '''interp bgerror''',

 > '''interp bgerror''' ''path target cmdPrefix''

was considered.  This alternative would have allowed background
errors in the ''path'' interp to be handled in the ''target''
interp.  The difficulty with this alternative was in how to
define the introspection form of the command.  Introspection
would need to return ''target'' information, and it would be
possible that the target interp of the handler would be 
an interp for which no ''target'' path could be constructed
to be returned (a sibling, parent, or uncle interp, etc.).

The proposed form can be combined with '''interp alias''' to
still allow background errors in one interp to (ultimately)
be handled by a command evaluation in a different interp.

~ Reference Implementation

See Tcl Patch 1060579.

~ Comments

Please make any comments here.

~ Copyright

This document has been placed in the public domain.
