Error management policy
For an overview of the SCOadmin error handling mechanism, see
``About SCOadmin error handling''.
The following points define the current policy for dealing with errors and
error stacks.
-
Errors are divided into three general categories:
-
Expected errors - errors such as invalid user input, missing files, incorrect
volume in drive.
-
Unexpected errors - errors that occurred because of an external problem, but
are not normally encountered in the course of using a program. These include
being out of system resource, system call failures, data file corruption and
external programs failing for unknown reasons.
-
Fatal errors - errors that normally indicate a bug within a program. This
include data structure failure and logic errors that can be detected. This
includes malloc failures unless a program is allocating large amounts
of memory in an indeterminate manner.
-
All programs must be able to recover from expected errors. This normally
includes asking a user to intervene and correct the problem. Making an
error stack available for a user to display often will help the user determine
the cause of the error.
-
Unexpected errors should be handled by gracefully shutting down the program.
An error stack should be made available to the user as the data might help
them correct the problem and rerun the program. The error stack should also
be logged.
-
Fatal errors are errors that usually cannot be diagnosed or corrected by a
user. When a program detects a fatal error, it should call one of the panic
functions as soon as possible. Trying to recover from a corrupt program is
usually not possible and can make the problem more difficult to resolve.
-
All return codes from system or library calls should be checked. This
includes close (close failure is normally a fatal error). Special
routines are provided to push UNIX errno error messages
onto the stack.
-
An error stack should contain data relevant to diagnosing a problem.
Great care must be taken in defining what is pushed on the error stack. Too
many inappropriate entries will confuse the user. Too little data will not
provide the user with enough information to determine the cause of an error.
-
Generally, the bottom entry in the stack should contain the error that occurred
and entries above that should contain the actions that were being performed
when the error occurred.
-
Where data such as file names are available they should be formated into the
localized messages.
-
Normally, a given function should only call one error manager push per
error instance. The function will then return to another layer, which can add
more information to the error stack if it has more meaningful data. The
exception is when a system or library call fails. Since the function is
returning its error in errno rather than a stack, one of the
PushUnixErr routines can be used to add two entries to the stack. If
a function is performing a complex operation, it might have enough information
to add more than one entry to the stack, but this probably means that the
function should be broken down into smaller operations.
-
Function names should normally not be included in the text of messages. The
localized text is aimed at the end user who does not have the source. If the
same error can originate from two different functions, then different message
IDs with the same localized text should be assigned for each instance. Having
the same error being returned in multiple locations often indicates the need
to provide a common routine to handle the function.
-
Since the message text is isolated from the code, message IDs should be
verbose and meaningful. They will only be typed a few times, they will be
read many times.
-
Error stacks should be allocated at the top level of a program and passed
down. Allocating intermediate error stacks should be avoided unless there
is a need to preserve an existing error.
-
The convention for clearing an error status is to clear it as part of the
error recovery code. Thus all procedures can expect an error status passed to
them has a value of OK and they do not need to clear the error status to
indicated success.
-
The error stack should be the last non-optional parameter to a procedure. In
C++ they should be passed as reference parameters rather than pointers. The
exception is for code were the error stack is optional or C++ code that is
callable from C.
-
The error stack should be the only reporting mechanism for an error. Use of
a functional return value is redundant and ambiguous. Leave the return value
free for returning data. Use the isOk field of the error stack to
indicate success or failure.
The following is a sample error stack returned from
data base code in
custom(ADM):
SCO_CUST_DBASE_ERR_DATA_OPEN
{Open of data file for database "system" failed}
SCO_CUST_DBASE_ERR_FILE_OPEN
{Open of database file "system.data" failed}
SCO_UNIX_ERR_EACCES
{Permission denied}
Error checking
The Server API takes care of a lot of the error handling which
needs to take place in an OSA. Whenever an error is
encountered, in the Server API or the OSA,
the code will push the error onto a known ``error stack'' for
future use by the Server API or the invoker
of the Server API. The
OSA writer will need to keep track of the following errors and
report them to the Server API when they are encountered.
During Validation Stage
The Server API does some minor error checking on the
arguments passed to
it. Most of the error checking must be done by the OSA.
The Server API will generate errors for:
-
specifying an attribute multiple times.
-
specifying an attribute which is already implicitly
specified via a group attribute.
-
passing attributes to the delete operation.
-
passing attributes with values to the get and
replaceWithDefault operations.
(SCO_OSA_ERR_INVALID_ATTRIBUTE_VALUE)
-
passing attributes without values to the replace, add, remove and
create operations. (SCO_OSA_ERR_INVALID_ATTRIBUTE_VALUE)
-
specifying an unsupported operation. (SCO_OSA_ERR_UNRECOGNIZED_OPERATION)
-
specifying an illegal attribute. (SCO_OSA_ERR_NO_SUCH_ATTRIBUTE)
-
specifying an illegal object class. (SCO_OSA_ERR_NO_SUCH_OBJECT_CLASS)
-
containing a garbled command. (SCO_OSA_ERR_MISTYPED_ARGUMENT)
-
specifying an illegal filter. (SCO_OSA_ERR_INVALID_FILTER)
-
Assigning set values to a single valued attribute. (SCO_OSA_ERR_INVALID_ATTRIBUTE_VALUE)
-
specifying an attribute without a value for the set, replace,
add, create or remove operation.
(SCO_OSA_ERR_MISSING_ATTRIBUTE_VALUE)
During Application Stage
When an OSA invocation includes a list of object instances,
Server API breaks it
down in the application stage and processes each object instance
individually. Each execution procedure should perform its intended
application as a whole or not at all.
Those that are run per attribute
should just be concerned whether there will be any errors effecting the
modification of that one attribute. If there are none, then the application
of the attribute's change can be completed. Otherwise the application of the
attribute's change should not be attempted.
Those that are run per object should be concerned whether they can
complete the entire operation without error or not. If the entire operation
can be completed, only then should it be done. If any error would occur then
the entire application should be aborted and the error returned.
The execution procedures should return one of the following errors
at the top of the error stack (other messages can be placed lower
on the stack):
SCO_OBJECT_LAYER_ERR_ACCESS_DENIED-
The invoker does not have permission to run the specified operation.
SCO_OBJECT_LAYER_ERR_DUPLICATE_MANAGED_OBJECT_INSTANCE-
The class is asked to create an object that already exists.
SCO_OBJECT_LAYER_ERR_GET_LIST_ERR-
The class encounters an otherwise unspecified error
in a get operation.
SCO_OBJECT_LAYER_ERR_SET_LIST_ERR-
The class encounters an otherwise unspecified error in a set,
replace, replaceWithDefault,
add, or remove operation.
SCO_OBJECT_LAYER_ERR_INVALID_ARGUMENT_VALUE-
The value passed to an action
in a argument is illegal or out of bounds.
SCO_OBJECT_LAYER_ERR_INVALID_ATTRIBUTE_VALUE-
The value passed to an operation or
filter in an attribute is illegal or out of bounds.
SCO_OBJECT_LAYER_ERR_NO_SUCH_ARGUMENT-
The value passed to an action does not exist, or has no meaning.
SCO_OBJECT_LAYER_ERR_NO_SUCH_ACTION-
The value action type passed to an action is unrecognized.
SCO_OBJECT_LAYER_ERR_INVALID_FILTER-
The filter function is unrecognized, a value is out of bounds, or otherwise
meaningless.
SCO_OBJECT_LAYER_ERR_INVALID_OBJECT_INSTANCE-
The named object instance violates the naming rules.
SCO_OBJECT_LAYER_ERR_NO_SUCH_OBJECT_INSTANCE-
An operation (not create) asked to run on a non-existent object.
SCO_OBJECT_LAYER_ERR_NO_SUCH_OBJECT_REFERENCE A create-
operation asked to base new object instance on a non-existent object.
SCO_OBJECT_LAYER_ERR_RESOURCE_LIMITATION-
A failure occurs because of a resource limitation.
These can be generated by these commands:
ErrorPush errStackVar throw messageId [argList] Tcl
ErrorPush(errStatus_cl *, const intlMsg_t *, ...) C/C++
Any execution procedure returning and error stack
without one of the previous
errors at the top of the error stack will have the
default message:
SCO_OBJECT_LAYER_ERR_PROCESSING_FAILURE
placed on the top of the stack. See
Error(TCL_ADM)
or
Error(S_ADM)
for more information.
Next topic:
Execution procedure data structures
Previous topic:
Return Value Structures
© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003