VFPUtils Article By: M. Asherman |
ErrHandler Development Tasks | |
---|---|
Taskid Date Done Priority |
Title Description |
---|---|
erma0026 (not done) |
revise and update article on VFP error handling references The article VFP Error Handling References has gotten a bit stale, and its organization could use a revamping. Here are some issues that should be addressed in a major overhaul:
|
erma0025 (not done) |
extensions for COM error handling ErrHandler does not yet include explicit provisions for COM/DCOM/ActiveX/OLE errors. (The mix of terminology is confusing, but these acronyms all pertain to COM-related issues.) The following extensions should be made:
Here are some COM-related references on the Fox Wiki: |
erma0024 (not done) |
RETURN TO ... .F. for non-local failure returns When a non-local return (i.e. RETURN TO ...) is used to handle certain kinds of failures (user Aborts and "unanticipated" errors), it would be most helpful to follow the convention that the return value is .F. Otherwise, to be strictly correct, one must often add an extra test (of the ehp_success property) to cover these relatively obscure types of failures. I would have followed this convention in the first place, but I had the mistaken impression that VFP doesn't allow specifying a return value in the RETURN TO ... command. The VFP 6.0 Help file specifies the following syntax for the RETURN command:
I tried the following syntax without success:
This gave me a syntax error, leading to my incorrect conclusion. I have since learned (thanks to Larry Miller on the Universal Thread) that the following syntax does work:
Note that the VFP Help file information is incorrect, because it implies one can have either eExpression or TO ProcedureName, but not both. Also the help information is misleading because it gives these options in the wrong sequence, and it happens to matter in this case. (That the sequence matters is yet another flaw, uncharacteristic of the FoxPro language in general.) |
erma0023 (not done) |
fix RETURN TO ... logic for known problem cases Certain core functions (errherr, errhoerrr, and errhshow) use VFP's RETURN TO ... command to make a non-local return, which skips over their direct caller in the program stack. (This is how user Aborts and "unanticipated" errors are dealt with.) Unfortunately, the logic for returning to the desired stack depth is kludgy and fundamentally flawed, primarily because of limitations in the VFP language itself (IMHO). Although the problem is somewhat obscure, I've occasionally encountered situations where the current logic doesn't work properly. The cause of these difficulties is that the name of the procedure to RETURN TO is not always obtainable [via the PROGRAM( ) function] in a simple, consistent syntax that can be used straightforwardly, if at all. For example, I recall having seen bugs where the error handler attempted to return to an ON ... command, which was triggered by a menu choice. The present kludge needs to be made even kludgier to deal with every possible case. Further review and testing will be needed to make this logic as robust as possible. I believe that a simple VFP extension (which must come from Microsoft) would entirely eliminate these problems, and I raised this idea in a discussion with Doug Hennig on the Universal Thread.on 1/4/01 (Subject: Error stack). My suggestion was that the RETURN TO ... command support a simple numeric stack depth argument, instead of requiring a potentially ambiguous and awkward-to-construct procedure name argument. Doug indicated that no such feature is included in VFP 7 or under consideration by Microsoft, to his knowledge. |
erma0022 (not done) |
include window caption info in diagnostic dialog's message text The diagnostic message dialog's window caption displays a title of the form <app_name> Error # <error_number>, and the scrollable editbox shows the rest of the error message. Originally, I deliberately avoided the redundancy of putting this title information into the editbox, since it seemed unnecessary. Now I realize that it would be much more convenient to include this redundant information at the start of the editbox contents, to make it easy to copy and paste the complete error information, without having to manually make note of the very important title info. There needn't be any redundancy in the way this information is shown in other contexts, e.g. WAIT WINDOW, output echoing, and logging to a text file. The proposed change only affects how error info would be displayed in the diagnostic dialog. |
erma0021 (not done) |
more flexible Resume command button implementation ErrHandler's diagnostic message dialog supports Suspend and Resume command buttons when used under the VFP Development System. The implementation is a kludge, because it depends on using certain features of the default VFP system menu. While I haven't yet discovered a cleaner solution that works, it would be possible to gain a small improvement in flexibility by introducing a new property that specifies the command to be used for supporting the Resume button's Click Event method. In the present implementation, the following command is executed in the Resume button's Click method:
I.e. the present implementation assumes that Ctrl+M (the VFP default) is the keyboard shortcut for Resuming a suspended program. At the very least, one should be allowed to substitute a different hot key, in order to allow for application-specific menu customizations. (It is also possible that VFP 7.0 may provide some cleaner alternative, but this needs to be researched further.) (Note that I tried the obvious approach of using VFP's RESUME command, as well as the less obvious alternative of SYS(1500, '_MPR_RESUM', '_MSM_PROG') to implement the Resume button, but neither of these techniques worked, presumably because they only operate from the VFP command window.) |
erma0020 (05/23/01) |
fix bug when system menus are unavailable under VFP Dev Sys When running under the VFP Development System, the diagnostic message dialog normally supports Suspend and Resume command buttons. However, if the application defines its own menus in such a way as to disable VFP's corresponding system menu bars, i.e. when SKPBAR('_MSM_PROG', _MPR_RESUM) is undefined, those buttons will not operate properly. The dialog's Refresh logic needs to check for this situation to avoid encountering an error. (Nadya pointed out this problem in email of 5/22/01.) Because the logic for supporting Suspend and Resume depends on system menu bars, it is recommended that you define your menus to include the standard VFP Suspend and Resume bar #s, _mpr_suspend and _mpr_resum, so that these form buttons can function. Otherwise, if SKPBAR('_MSM_PROG', _MPR_RESUM) is undefined, the diagnostic message dialog's Suspend and Resume are disabled, to avoid the risk of errors. Since the diagnostic message dialog may be called from an error handler, we settle for this conservative "dumb" mode instead of risking a nested error, which can't be handled in VFP. If you want to support Suspend and Resume under the VFP Development System, be sure to incorporate VFP's Suspend and Resume system menu bar #s in your own menu system, or use the standard VFP menus. Also note that the Resume button logic depends on VFP's standard Ctrl+M shortcut, because if uses a KEYBOARD hack. (This kludge really should be made a little more flexible, but I'll deal with that rather obscure limitation later, under a separate task.) |
erma0019 (01/28/01) |
don't propagate ehp_interactive along with diagnostic properties This is a small revision to the specs for errhdiag( ). I had originally thought it would be sensible to treat ehp_interactive like other diagnostic/tracing/output options. Upon further reflection (in the course of xfma0072), I've concluded that it was a mistake to include ehp_interactive among the properties that are inherited via target indirection. Whether a sub-application (specifically, like XFormDBF or BTCrit) is invoked interactively or non-interactively is determined by an explicit caller-supplied argument, so there is no need to provide another initialization mechanism. Furthermore, it is not necessarily the case that an interactive caller (e.g. Job Control) will want to invoke the sub-application in its interactive mode, so it doesn't make sense to "inherit" interactiveness from the master application. On the other hand, it still does make sense and is a genuine convenience that true diagnostic options (like ehp_diagmode, ehp_tracelevel, etc.) should be propagated by errhdiag. |
erma0018 (not done) |
options for dealing with multiple consecutive errors Generally one doesn't want to encounter a series of errors that are really the result of a single initial error, which should have been handled in such a way as to avoid spurious secondary errors. Nevertheless, it is possible that there could be multiple consecutive errors in certain cases. Consider making adjustments to the present error handling logic, perhaps as an option, so that consecutive errors behave in a reasonable, consistent way. This will require some further thought, but it seems to be a legitimate issue. For example, one question is what error information to return. The current logic will generally return information about the last error that took place. A better default might be to return info about the first of a series of errors, since this is much more likely to be the real indicator of the original problem. |
erma0017 (01/22/01) |
propagate Aborts and error info up the target indirection hierarchy Extend the logic for target indirection to iterate or recurse through however many levels of target indirection may exist. Previously, errhcopy would only propagate error information to the immediate target. Generalize this logic to let the immediate target propagate to its indirection target, and so on, until a terminal ErrHandler is reached. Also take this opportunity to optimize errhcopy logic for the most common non-error cases. Likewise, let Aborts be propagated up the stack, along the target indirection hierarchy, but introduce a new property, ehp_abortstopshere, to optionally force the Abort not to be propagated past a certain point. Introduce a new subclass of ErrHCustom, ErrHCustNoAbort, having ehp_abortstopshere = .T., for use as a terminal ErrHandler. ErrHCustDiag should be redefined as a subclass of ErrHCustNoAbort. This change simplifies the use of nested ErrHandler objects, because it avoids the necessity of adding extra "wrapper" logic around calls to subordinate ErrHandler methods; the change enhances symmetry between an object's own methods and those of the nested ErrHandler. (This has immediate application to XFormDBF, an ErrHForm-based application that uses Commander, based on ErrHCustom.) |
erma0016 (01/13/01) |
revise specs for default RETURN depth on user Aborts Previously, when the user deliberately exited from the diagnostic message dialog by clicking Abort, a non-local return (via RETURN TO) was made by default. Change the logic in errhshow to make the default behavior on Abort be what amounts to a normal return to the procedure that called EHM_ShowAppErr, instead of popping the stack straight back to the caller of that procedure. This allows the method that invoked EHM_ShowAppErr to fail in its normal way, making the treatment of Aborts more symmetrical to other error cases. Be sure that all callers of EHM_ShowAppErr( ) take the possibility of an Abort request into account. (Generally this won't require any logic changes, because the usual scenario is that a call to EHM_ShowAppErr( ) is immediately followed by a failure return.) This change should alleviate problems of the kind of that led to erma0013. The EHM_ShowAppErr method and its corresponding core UDF, errhshow, support an optional argument, aborto_arg, for specifying a relative RETURN TO stack depth. This argument is intended primarily for internal use by the catch-all error handlers, errherr.prg and errhoerr.prg, and would generally be omitted otherwise. The previous default value of aborto_arg was interpreted to mean that the an Abort should pop back to the caller of the caller of EHM_ShowAppErr, which is therefore the caller of the caller of the caller of errhshow. In the revised specs, the default aborto_arg value (empty or zero) means to just return to the caller of EHM_ShowAppErr. Under the new specs, aborto_arg = -1 would now designate what was previously the default. In other words, aborto_arg is the stack depth to RETURN TO relative to the caller of EHM_ShowAppErr, if the user Aborts. Also make a slight change in specs for errhzero (hence the EHM_Zero method as well) to include ehp_aborted among the error properties that are cleared. There is no good justification for treating this property asymmetrically. In any case, failure/cleanup logic must take care not to call EHM_Zero after an error has taken place. |
erma0015 (01/09/01) |
optionally display the whole program stack in errhvfms( ) Beef up the VFP error information displayed in core UDF errhvfms.prg to include a snapshot of the entire program stack below the point of error. This will be helpful in making sense of unexpected error messages. Since it may be an annoying level of verbosity, introduce a new property, ehp_showstack, which can be turned off to suppress display of additional stack info. Make the default be to display this info, since it's more likely to be useful than not. Add this property to list of those that are propagated via errhdiag( ), to make it easy to treat this as a global diagnostic option. Note that the demo screen shots really should be updated to show the program stack info that is now appended to error messages by default, but this can wait. As it stands, these screen shots reflect what happens if ehp_showstack = .F. |
erma0014 (01/03/01) |
allow for self-destruction while the diagnostic dialog is active Adjust errhshow.prg to be able to cope with self-destruction in progress when the modal diagnostic message dialog returns. This is needed to allow for the possibility that the user can click on the main VFP window close box while the diagnostic dialog is active. An ON SHUTDOWN handler may be used to trigger the self-destruction, so errhshow needs to be prepared for this situation. |
erma0013 (01/01/01) |
use ehp_success instead of return value from errhtarg( ) When the user does an Abort (via the diagnostic message dialog) from an error reported by errhtarg( ), a RETURN TO ... command pops the stack directly back to the Init method, but this mechanism has no way to control the function return value. Check the ehp_success property instead of depending on the return value from errhtarg in the Init method logic for foundation classes, ErrHForm and ErrHCustom. This is necessary to assure that user Aborts from such errors are always processed without delay. |
erma0012 (not done) |
further help documentation updates The ErrHandler help pages need a few more small revisions to be brought in synch with recent program changes, for example:
|
erma0011 (not done) |
make appropriate use of ASSERT for usage errors Previously, when an error was detected while error handling features were not available, I would just punt by using WAIT WINDOW. This situation arises, for example, in the core error handling functions themselves, e.g. when the required ErrHandler object reference is unavailable because of a programming error. It may be better to use ASSERT than WAIT WINDOW in many cases, to make debugging easier. A major limitation of ASSERT, however, is that it doesn't work in a VFP Runtime environment, and it only works if SET ASSERT ON has been run. Also note that SET ASSERT OFF is the default, so this type of error checking may be unintentionally rendered ineffective. |
erma0010 (12/28/00) |
pick up default diagnostic/tracing properties via target indirection Revise specs to support a more convenient way of initializing properties related to error and diagnostic tracing message output. In the Init method, if a target ErrHandler object has been specified, let its properties be propagated to the new object as initial default values. This applies to the following properties only: ehp_diagforce, ehp_diagmode, ehp_echodebugout, ehp_echologfile, ehp_echoscreen, ehp_interactive, ehp_log_function, ehp_logfilepath, ehp_pathtypedefault, ehp_tracelevel, and ehp_tracequietly. Introduce a new method, ehm_copydiags, to handle the details of copying the above properties from one ErrHandler to another. Let errhtarg.prg invoke ehm_copydiags to handle the new propagation logic. Also introduce a new core UDF, errhdiag.prg, which does the actual work for method ehm_copydiags. Also create a new subclass of ErrHCustom, called ErrHCustDiag, which differs only by the setting of ehp_diagmode = .T. The rationale is that these properties govern variable modes of message handling that would typically be global settings, and this is a convenient way to propagate the current settings. Individual per-object properties can still be adjusted manually, if desired, but that should seldom be necessary in typical usage. |
erma0009 (12/04/00) |
introduce a core UDF for foundation Error event methods To minimize redundant logic and simplify global changes across ErrHandler foundation classes, introduce the new errherr( ) core function. This will be helpful for diagnostic error handling extensions and other error handling refinements. Adjust ErrHandler Help - Foundation Classes and Core Functions to keep documentation in synch with changes. Highlights of changes incorporated into this version errherr.prg:
|
erma0008 (11/10/00) |
optional ErrHandler Init argument for target indirection In addition to the properties already provided for target indirection, it would be useful to support an optional Init event method argument for supplying an explicit object reference pointing to the target ErrHandler. This is simpler, more efficient, and more flexible than property-based initialization. Saver's initialization logic needs this change in order to fully handle errors when it attempts to instantiate a temporary Commander object via newobject( ). This is really a further extension of previous changes for support of nested ErrHandlers. Adjust ErrHandler Help - Foundation Classes and Core Functions to keep documentation in synch with changes. Also note these related issues:
|
erma0007 (10/26/00) |
changes for support of nested ErrHandlers Add some properties and adjust methods/core UDFs to provide greater convenience in support of nested ErrHandler-based functions. This will be helpful in the forthcoming Saver/Commander error handling changes. Programming changes required for ErrHandler:
Test these changes via the ErrHandler demo application, plus direct use of the VFP command window and Debugger. Adjust ErrHandler Help - Foundation Classes and Core Functions to reflect the above changes. An example of nested ErrHandler usage would also be handy in ErrHandler Help - Usage, but hold off on this until we've got a real example in Saver's calls to Commander, i.e. after redefining Commander as a subclass of ErrHCustom. |
erma0006 (08/19/00) |
article summarizing useful VFP error-handling references Create an quick- reference article on VFP error-handling resources, available both online on the web and on MSDN CDs. (Note that links to pages within MSDN's HTML Help files can be created by using the special-syntax URL's that can be obtained via the Jump to URL... command buried in HTML Help's control menu.) As a further refinement, introduce a sub-section of the main Contents outline in order to give a topical breakdown of these references. This is similar to the way we've organized task lists into an tasks outline and an accompanying tasks table, i.e. this page. (The benefits of this organization become clearer when one uses the framed mode of browsing.) Maintain notes about further changes and ongoing maintenance of this reference page in a section at the bottom of the article. |
erma0005 (12/04/00) |
support a flexible default form-level error handler The present ErrHandler facilities allow method code to explicitly provide highly context-sensitive error handling logic, as opposed to depending on a global ON ERROR handler. This makes it possible to produce more meaningful error messages and return codes for anticipated error situations, as well as making it possible to fail more gracefully than a context-insensitive ON ERROR handler. However, as previously noted (which Doug Hennig points out in his very helpful article, "Error Handling in Visual FoxPro"), one really needs an additional layer of error handling for cases where there is no explicit error-checking, to perform required cleanups and terminate properly in all cases. In other words, we need a way to specify default form-level error-handling logic that allows the form to fail cleanly without taking the overly heavy-handled action of terminating the entire application. The same idea could also be applied to other classes of error-handling objects, but the ErrHForm foundation class is a good starting point, because this is the basis for some existing applications with fairly complex and rigorous error-handling requirements. In particular, we want to ensure that Saver-based forms like XFormDBF and BTCrit can handle unanticipated errors at least to the extent that they do the following:
If there were no such form-level ON ERROR handler, VFP's default handler would be triggered. But for Saver-based forms, we would generally want to suppress automatic state-saving before terminating the form abnormally, and this should be the responsibility of the form itself, not the application that called it. Instead of choking on a low-level VFP error, the less disruptive standard error return mechanism should be used, so that the failure is localized and the caller (e.g. the JobControl application) can continue with its normal processing. Prior to this change, the user of a Saver-based application needed to manually Abandon the form in such cases, or else risk losing the current configuration. |
erma0004 (12/01/00) |
diagnostic error-handling options Support an optional dialog, as mentioned previously, that gives the user some choices about what to do when an error is trapped in an Error event or an ON ERROR handler. This would be similar to VFP's default Program Error dialog, which displays a VFP error message and gives the choices: Cancel, Suspend, Ignore, and Help. Additional choices might include Retry, Debug, and other more graceful ways of failing than Cancel. (Suspend and Debug are only available under the VFP Development System, so it might be useful to support a diagnostic display of the program call stack that could be used in a pure runtime environment, but hold off on this for now.) Details about this group of changes::
|
erma0003 (12/02/00) |
provide a flexible mechanism for automatic error logging Support an optional way of capturing error information in a log file, which may be stored as a table. For the sake of modularity and flexibility, establish an API for connecting to an external, application-specific error logging function, specified via the ehp_log_function property. The logic for invoking this logging function would go into the core error-reporting function, errhshow( ). (Note that this is separate from the basic ASCII text log file, ehp_logfilepath, which can be controlled from the diagnostic message dialog.) The external logging function should conform to the following API, which is essentially the same as the interface to errhshow( ), up to the first 4 arguments:
|
erma0002 (10/07/00) |
developer-oriented help for ErrHandler facilities Create HTML pages of help documentation for the ErrHandler classes, supporting functions, and the error-handling demo application. Also compare with similar task for the Saver subsystem, and see SplitCon Help - Design Overview as another example of developer help. Expand on previous preliminary documentation. |
erma0001 (not done) |
assimilate old errhandl.txt task list into new HTML task list Go through the old ErrHandler task list and create updated entries in the new ErrHandler task list (this table and its outline) for selected issues that are still of interest. |