Error Handling Manual

Ralph Johnson

June 9, 1998

Doc$User: ERROR_HANDLING_MANUAL.PS

Notices:

  1. No changes have been made to the output format of existing error routines.
  2. You can continue to use the existing error routines in C& Fortran code.
  3. For now, for compatibility with its existing usage, ERR_SEND does not utilize any of the new code.
  4. Please remember that this is a new facility and will be evolving as it is used more and more. If you find that there is some functionality which is not provided, rather than adding a work-around, please let me know so that the functionality can be added.

Purposes

  1. Provides functions which can be used within C++ to do err_send & err_text calls using the existing argument format.
  2. Supplements the existing error routines for use in C++ facilities.
  3. Provides a means to add more contextual information to error output.
  4. Provides a means to direct error output information to additional and multiple destinations.
  5. Provides functions callable from C & Fortran to utilize the new features
  6. Intended to be used for errors occurring in AST routines. However, this is not yet available.
  7. Provides the ability to propagate an error and its context to a level where there is access to needed output functions.
  8. Provides a means by which a fuller context in which an error occurred can be provided as the error is propagated upward through the layers of an application.
  9. Provides a means by which an error and the full context in which it occurred are available for analysis or use prior to any output.
  10. Provides a means by which applications can have their own special handler functions to deal with error incidents.
  11. Provides the ability to handle error conditions generated within the RTL, the STL, user applications, and possibly VMS.

Definitions

  1. error instance - An instance of a class of an error object.
  2. error incident - This is the occurrence of a single error and includes all error information created in reacting to the error.
  3. incident severity - The worst of the severities of all ErrCondition_C items in the error incident unless there is an ErrSeverity_C item. Then the incident severity is the severity of the last ErrSeverity_C item created.
  4. incident handler - A routine which generates the output for an error incident.
  5. incident destination set - The set which includes all destinations of all items of the error incident.
  6. RTL error -This is an error detected within the code of a RTL function.
  7. STL error - This is an error detected within the code of the STL.
  8. VMS condition - An error condition detected by VMS such as an access violation or floating point overflow.
  9. VMS exception - The item created by VMS when a VMS condition is detected.
  10. Exception object - A class of objects used for VMS conditions.
  11. STL exception object - An exception object thrown from within a STL function.
  12. Unix signal - A Unix style condition which can be used in the RTL. However, in the SCP and our other standalones it cannot be used.

Comparison of C & Fortran layering to C++ layering.

Within C and Fortran, condition codes are returned from function to function. Within C++, error objects are thrown from function to function.

C & FORTRAN C++

 

FunctionA() CppFunctionA()

iss object(iss,data,dest,time)

FunctionB() CppFunctionB()

iss object(iss,data,dest,time)

FunctionC() CppFunctionC()

iss object(iss,data,dest,time)

FunctionD() CppFunctionD()

error detected error detected

 

THE DETECTION OF ERROR CONDITIONS.

Application Errors

These are detected within application code in a variety of ways. They may be status returned by hardware, something not completing, etc.

Errors Occurring Within A RTL Function.

If an error is detected within a RTL function and the fact that there was an error can be returned by the function, it does so and the external symbol errno is set to a value which indicates why the error occurred. See the DECC runtime library manual.

If an error indication cannot be returned from the function, a VMS exception is generated as might occur in application code. These can be detected by the use of the VMS exception handling functions. See the VMS condition handling sections in this document.

Errors Occurring Within A STL Function.

When an error occurs within a STL function an exception object is thrown. It can be caught by a catch(exception&); statement in a C++ routine. See the VMS condition handling sections in this manual and the DEC help files on the exception class.

Other Error Conditions Detected By Vms During Code Execution.

These can be detected by the use of the VMS exception handling functions. See the VMS condition handling sections in this document.

THE HANDLING OF ERRORS WHERE AN ERROR IS DETECTED.

When an application function detects an error it must pass the fact of the error to the function which called it.

Fortran & C Functions.

These functions should return a VMS condition code as the function return.

C++ Functions.

These functions should instantiate an ErrCondition_C object or an object of a class derived from ErrCondition_C and then throw the pointer to the object. Such as:

Err_C* err_po = new ErrCondition(FACILITY_ERROR);

throw err_po;

If additional information is available it be included in the error incident by also instantiating an ErrContext_C object. Such as:

new ErrContext(While doing something.);

 

THE HANDLING OF A NOTIFICATION THAT AN ERROR HAS OCCURRED IN A CALLED FUNCTION.

Fortran & C Functions.

These functions should pass on to their caller the condition code returned to them by called functions. See REF_DSPSHR:Demo_Cfunc.c.

C++ functions.

  1. These functions should catch an Err_C*.
  2. If there is further information to be added, an ErrContext_C object should be instantiated.
  3. If the function decides that the incident output should be sent to additional destinations, an ErrDestination_C object can be instantiated.
  4. If the function decides that the incident severity should be overridden to a new severity, an ErrSeverity_C object can be instanciated.
  5. Usually the function then rethrows the Err_C* it received.
  6. However, it may have the incident processed and then either continue or instanciated and throw a new error condition.
  7. See REF_DSPSHR:Demo_CppFunc.cxx.

HANDLING THE NOTIFCATION OF AN ERROR FROM WITHIN A C++ FUNCTION WHICH IS A CALLING INTERFACE BETWEEN A FORTRAN OR C FUNCTION AND A C++ FUNCTION.

These functions should catch an Err_C*, extract the condition code from it, and return the condition code as their function return. See REF_DSPSHR:Demo_CppFunc_cfn.cxx.

STANDARD OBJECTS WHICH CAN BE THROWN AND CAUGHT.

These are the objects which can be thrown and caught by C++ routines for the purpose of passing an error condition and its context upward through layers of applications. The formats shown here only indicate the types of arguments that can be used. The exact formats are in the class definition (header/.hxx) file for each class.

ErrCondition_C (condition [,data][,destination])

This class provides for the instantiation of an object which contains a condition code, optional data, and an optional output destination. Also see: ErrCondition_C.hxx and REF_DSPSHR:Demo_C.cxx

ErrIss_C is a typedef for ErrCondition_C and can be used in its place if desired.

ErrContext_C (data [,destination])

This class provides for the instantiation of an object which provides contextual information for an error incident, and an optional output destination for the information. Also see: ErrContext_C.hxx and REF_DSPSHR:Demo_CppFunc.cxx.

ErrDestination_C (destination)

This class provides for the instantiation of an object which provides an additional output destination for an error incident. The total set of output destinations for an incident is the set of all destinations of all objects included in the incident. Also see ErrDestination_C.hxx and the Destinations section of this document.

ErrSeverity_C (condition_code)

This class provides for the instantiation of an object which provides an overriding severity for an error incident.

If there is more than one of these in an incident, then the last one entered for the incident will be the one used.

Also see: Err_C.hxx.

Severity refers to the severity of a condition code. It is one of the following: SUCCESS, INFORMATIONAL, WARNING, ERROR, or SEVERE.

ErrSend_C (iss, args...)

This class provides for the instantiation of an object which results in output which is the same as the legacy ERR_SEND() function used in Fortran and C functions. It has been implemented to provide compatibility with the old style. Within C++ one should, instead, instantiate an ErrConditon_C object, providing a UtlArgs_C object as the data.

ErrText_C (iss, string)

This class provides for the instantiation of an object which results in output which is the same as the legacy ERR_TEXT() function used in Fortran and C functions. It has been implemented to provide compatibility with the old style. Within C++ one should, instead, instantiate an ErrConditon_C object, providing a UtlString_C object as the data.

ErrDelimit_C()

This class provides for the instantiation of an object which delimits error instances. It is to be used in AST routines as more than one instance may occur before the queue is processed. It should be instantiated after all other error instantiations in an AST routine prior to the AST function return.

UTILITY DATA CLASSES WHICH CAN BE INCLUDED IN AN ERROR OBJECT.

These are the classes which can be used as the data of ErrCondition_C, ErrSend_C, and ErrText_C objects.

UtlString Class (string)

This class provides string data. It is instanciated by supplying a null terminated string. In the future you will also be able to include a font and a color.

UtlTime Class()

This class provides time. It has member functions to retrieve the time in rtl type, system type, or as a null terminated text string.

UtlStl Class

This class provides data associated with a Standard Template Library class. It is instanciated by providing a reference to an exception class object which then becomes the object's data.

UtlSignal Class

This class provides data associated with a VMS exception. It is instanciated by providing a pointer to a VMS signal structure. The data contained in the object is the condition code obtained from the signal structure.

UlArgs Class (arg1, arg2, ..., arg10)

This class provides data which is associated with the arguments of the VMS error message facility. It is instanciated by providing from zero to ten pointers each of which points to a four byte argument. The data contained in the object is the set of the four byte contents of the argument pointers.

UtlSlcDbDevice_C

This class provides data which is the identification of a SLC database secondary. It contains the primary,micro,unit,secondary, and channel.

UtlEpicsDevice_C

This class provides data which is the identification of an Epics database value. It contains up to 4 record subnames and the field name. VAL is used as the field name if none is supplied.

UtlDcxpDevice_C

This class provides data which is the identification of parameters used in the DCXP, SIP, and HSTB facilities. It contains either a SLC database primary, micro, unit. secondary, channel identification or a special device, area, unit, parameter identification which is used only within these facilities. A special dcxp parameter name can be used in place of the secondary name for SLC database items. See DCXP, SIP, or HSTB manuals.

UtlHelp_C

This class provides data which is the specification of a help file entry from which text is obtained for output. You provide a set of semicolon separated keys as a null terminated string such as: DISPHELP;MODULE;KEY1;KEY2;...

DESTINATIONS FOR ERROR INFORMATION.

These are the destinations to which error information can be sent. Also see: Err_C.hxx.

The current SCP error handler will output all information to all destinations contained in the incident.

Default Output

This is a special destination which is specified by Err_C::DEFAULT_DEST. For this destination the output is generated by the class default output routine. See the class header files.

  1. The ErrSend_C class default output is that of ERR_SEND (the error log and the global message window).
  2. The ErrText_C class default output is that of ERR_TEXT (the error log).
  3. The ErrCondition_C class default output is that of ERR_TEST (the error log).
  4. The ErrContext_C class default output is no output.

Notification Window.

This destination is the popup operator notification window. It is specified by Err_C::NOTIFICATION_WINDOW_DEST. When output is sent to the window it pops up over the touchpanel in front of the operator. It is dismissed by the operator clicking its cancel button.

Status Bar (currently used only by the knobs panel).

This destination is the status bar on the knobs panel. It is specified by Err_C::STATUS_BAR_DEST. When output is done to this destination only the data from the first instantiated object of the incident is displayed in the bar. However, when an operator clicks on the status bar a status window pops up with all output which has been sent to the status bar destination.

For now, the output also goes to the local message window of the SCP.

USER_FILE_DEST

This destination is a user specified file. The error facility opens and writes to a file named: USER_ERROR_FILE. If you wish, you can define this as a logical to be whatever file you want it to be.

ERRLOG_DEST

This destination is the errorlog file.

LOCAL_MSG_DEST

This destination is the operator local message window.

BROADCAST_DEST

Broadcast to all processes receiving messages. For the SCP these go to the global message window.

Adding Error Objects To An Incident From Within C Functions.

These functions can be called from C functions to instantiate a objects to be included in an error instance. There names are not mangled. See err_faciilty.h.

ErrConditon_Create.cxx

This function creates an instance of an ErrCondition_C object. A vmsstat_t condition code and a null terminated string are the only argument types available.

ErrContext_Create.cxx

This function creates an instance of an ErrContext_C object. A null terminated string is the only argument type available.

ErrSend_Create.cxx

This function creates an instance of an ErrSend_C object. A variable length argument list of pointers to 4 byte data items is used.

ErrText_Create.cxx

Tis function creates an instance of an ErrText_C object. A null terminated string or a string descriptor can be supplied as the argument.

Err_OpNotify.cxx

This function creates an instance of an ErrContext_C object specifying the status bar as the destination. A null terminated string is the only argument type available.

ErrDestination_Create

This function creates an instance of an ErrDestination_C object. It adds the specified destination to the set of destinations for the output of an error incident.

ErrSeverity_Create

This function creates an instance of an ErrSeverity_C object. The specified severity overrides the severities of any entries made for an error incident. If more than one ErrSeverity_C object is included in an error incident, the last one entered is the one used.

Err_HelpContextDsc

This function creates an instance of an ErrContext_C object, supplying it with a UtlHelp_C object as data. The UtlHelp_C object is created using the string passed to this function by descriptor.

CREATING AN INCIDENT FROM WITHIN AN AST ROUTINE.

The error handling system can be used from within an ast routine. To do so you:

  1. Call ErrQueue_C::CreateQueue().
  2. Save the returned queue pointer in a static variable.
  3. Use the Err..._C creation function signatures which include a queue pointer argument to instantiate objects to b included in the incident.
  4. DO NOT THROW ANY OF THE CREATED OBJECTS.
  5. Prior to returning from the AST function instantiate an ErrDelimit_C object to delimit the incident.

The process executive will call the current handler for the queue that you have created.

CLASS TYPING

All error classes which are available for public usage are in a class hierarchy derived from the Err_C class. All utility data classes are in a separate class hierarchy derived from Utl_C. Each hierarchy provides a complete set of class typing functions. See Err_C.hxx and Utl_C.hxx.

ERROR PROCESSING

Setting up a process to use the error facility.

  1. If you do nothing, no entries will be made in an error queue. If the error facility is not specifically enabled when an instance of an error object is created, the object will not be inserted into any error queue. Rather, the default output routine of the class will be called and then the object will be deleted if necessary. In this case you can only use the C callable routines which instantiate error objects.
  2. To enable the error facility to be able to use all of its functionality, you call ErrFacility_C::Enable(); which also means that you need to be in C++.

ErrFacility_C* err_facility_po = ErrFacility_C::ErrFacility();

err_facility_po->Enabled(True);

  1. At any point in the execution where error information needs to be output, there must be a call to have any current incident processed. This is done by calling ErrFacility_C::ProcessIncident(). For example, this would be needed at the end of each iteration of some loop wherein errors might be encountered and need to be output before all iterations are completed.
  2. In the main routine of the process there should be a catch(Errs* err_po) block which means that the main routine, or some part of it, would be within a try block. Within or after the catch block ErrFacility_C::ProcessIncident() would be called.

Note that a try-catch-process situation can be inserted anywhere in the process execution where error output is to be done.

Standard Error Processing by the Process Executive.

  1. Any thrown Err_C objects (pointers) are caught by the process (e.g. SCP) executive. They are not rethrown so that they do not propagate any further.
  2. The current incident handler is called for each error queue. The handler generates all output for the inormation contained in the incident.
  3. After any incident in an error queue has been processed the current handler function for the queue is reset to the process's standard handler.

Supplying A User Handler To Be Used When The Executive Processes An Incident.

Call ErrQueue_C::Handler(user_handler_function(), &user_data); to specify a handler to be used for any current incident. Note that it must be re-specified each time the executive calls an application facility. However, it does not need to be called prior to any items being instanciated for an incident, only prior to control being returned to the executive.

Error Processing From Within An Application.

  1. The current incident can be caused to be processed within application code at any time by calling Err_ProcessIncident(0,0) from C code or ErrFacility_C::ProcessIncident(0,0) from C++ code.
  2. ErrFacility_C::ProcessIncident() is overloaded so that you can supply a handler to be used and a user data pointer. See ErrFacility_C.hxx.

Clearing An Incident From Within An Application.

  1. The incident can be cleared (all items removed) at any time by calling Err_ClearIncident() from C code or ErrFacility_C::ClearIncident() from C++ code.

Errors Detected Within The Error Handling Facility.

When an error is detected during the execution of the error handling facility code, a fatal VMS condition is signalled and the process will abort.

ASSISTANCE IN USING THE ERROR HANDLING FACILITY.

Documentation:

This user manual: DOC$USER:ERROR_HANDLING_MANUAL.PS.

There is also the design document (not quite up-to-date): DOC$DESIGN:ERROR_HANDLING.PS.

Demonstration code:

There is a Demo facility within the scp that utilizes the facility.

By selecting the DEMO panel from the user dev panel you can press buttons which create various errors which generate output to various destinations.

The Demo... code in dspshr can be used for reference or as template code. See REF_DSPSHR:Demo*.*.

The following routines contain the various functions which can be used: Demo_AllCalls.cxx, Demo_AllDestinations.cxx, Demo_QueAllCalls.cxx, Demo_AllOperators.cxx, and Demo_ForC.cxx.

Error Facility Code:

The code and classes of the error facility contain most of the C++ issues that one migh t normally encounter when developing any C++ facility.

VMS'S HANDLING OF ERROR CONDITIONS (FYI).

All information contained in this section reflects my current understanding of how things work. It is subject to change.

Note: Currently there is a VMS problem using cxxl

VMS Error Conditions Raised In Application Code.

When a VMS error condition is raised within application code a VMS exception is generated. It is processed by the first VMS exception handler encountered moving down the stack.

If the VMS signal is rethrown (throw;), the next catch(struct chf$signal_array* ps) or VMS condition handler lower on the stack will be called.

If the VMS exception does not have an equivalent Unix signal, the VMS exception can be caught by catch(struct chf$signal_array* ps). If it does have an equivalent, it will not be caught.

However, if cxxl$set_condition(cxx_exception) is in effect when a try block is entered (has been called prior to the try block) then a VMS exception which has an equivalent Unix signal can be caught by a catch(struct chf$signal_array* ps) after the try block.

Application Error Objects Throw By Application Code.

When an error is detected within application code and a throw is done a VMS exception is generated which is caught by a VMS exception handler established by a catch statement.

Errors Within RTL Functions.

When an error occurs within a RTL function.

If it is an error which can be returned from the function, the fact that there was an error is returned and errno is set to indicate why the error occurred. errno is actually a macro which generates a function call.

If an error indication cannot be returned, a VMS exception is generated.

Errors Within the STL.

When an error occurs within a STL function an exception object is thrown. It can be caught by catch(exception&) in a C++ routine. Note that this is an exception object not a VMS exception.

EXCEPTION HANDLERS (FYI).

All information contained in this section reflects my current understanding of how things work. It is subject to change.

catch()

In C++ routines if cxxl$set_condition(cxx_exception) has been called, then a VMS signal can be caught by catch(struct chf$signal_array* ps). If a rethrow is done the VMS signal will continue to be processed.

If cxxl$set_condition(cxx_exception) is in effect, an a RTL signal handler is called and will not return.

LIB$ESTABLISH

If a VMS signal reaches the call frame of the routine which calls LIB$ESTABLISH, then the exception handler specified in the call will be called.

If the exception handler return is a resignal, the VMS signal will continue to propagate down the stack.

If the handler return is a convert to status, the stack will be unwound thru the routine which called LIB$ESTABLISH and the condition code contained in the VMS signal will be returned as the function return.

sig... RTL functions.

Note: At this time in the SCP and in our standalones these RTL functions cannot be used as they conflict with our use of VMS exception handlers.

The sig... RTL functions can be used to control what action to take or what handler to call when a unix signal (or any of a set of unix signals) is processed. For this to happen a VMS exception must reach a RTL VMS signal handler where the VMS exception can be processed.

If VAXC$CRTL_INIT is explicitly called, it establishes the RTL handler at the bottom of the stack regardless of wen, or how many times, it is called. If it is not called and the main process routine is not a C or C++ routine, no RTL handler will be established.

If a LIB$ESTABLISH VMS exception handler has been established the RTL handler will only be called unless the exception handler resignals the exception. It does not matter in what order the VAXC$CTRL_INIT and LIB$ESTABLISH calls are done.

If cxxl$set_condition(cxx_exception) has not been called, and a handler established by signal(signal_code, handler) is called and does a return;, execution will continue after the signal() call.

If cxxl$set_condition(cxx_exception) has been called, the "last chance" handler is called when the signal handler returns.

METERING OUTPUT

If you wish to have error incident output metered, you can instantiate a destination object with an attached meter object. If any output is suppressed, a counter for the output is incremented and when the output is finaly done, the count is appended to the output.

For now only the meter object most recently entered into the error instance will be used and the metering will be applied to all incident output.

If needed, the facility can be enhanced such that output to specific destinations can be metered separately.

To have metering applied to the incident:

  • instantiate an ErrMeter_C object.
  • instantiate an ErrDestination object specifying NO_DEST (or any destination) as the first argument and supplying the pointer to the ErrMeter_C object as the second argument.
  • Types of metering.

    Two types of metering are provided for. The type is determined by which ErrMeter_C constructor is used.

    ErrMeter_C(const UtlTime_C& interval, unsigned long id)

    Only one output is allowed during any interval of time.

    ErrMeter_C(long burst_count, UtlTime_C& burst_interval, UtlTime_C& reset_interval)

    If the burst count is exceeded within the burst interval then metering will begin and continue until there have been no more incidents the same incidents within the reset interval.