Ingres CL EX
From Ingres Community Wiki
|
Ingres Compatability Library |
Compatibility Library Specification - EX 1.2
Abstract
This is the specification of the EX facility provided by the compatibility library for handling exceptions.
Revision: 1.2, 12-Feb-1998
Document History
- Revision 1.2, 12-Feb-1998.
- Change EXCONTEXT to EX_CONTEXT.
- Convert to HTML.
- Revision 1.1, 29-Jul-94.
- Note that EX_xxx is an exception; EXxxx is a return; handlers return STATUS. (20-mar-92)
- EX_BADCONTEXT should not exist (27-mar-92).
- EX handling of UNIX signals isn't what anyone wants (4-sep-92, 26-feb-93
- Revision 1.0, last modified 29-Aug-91
- Limit arguments to EXsignal as 4, add EX_MAX_ARGS definition.
- Added overlooked MH exceptions, EXTEEOF, EXDECDIV, MH_BADARG, MH_INTERNERR, MH_MATHERR, MH_PRECISION.
- Fixed typos.
- Cleared up exargs_count once and for all. It's the number of elements in the exargs_array[].
EXEXIT has no special meaning within the CL. It's just another client-known exception.
- Revision 6.3/02, October 1990
- Here are some the notable changes from earlier versions of the description of EX.
- Handlers must return STATUS, not i4 or EX or longnat. This is because EXdeclare, which returns a status, must return EXDECLARE. This changes the type of function pointer given to EXdeclare.
- The argument to EXmath is now a nat, not an i4. This is to allow consistant declaration of EX_ON and EX_OFF, which are also used as arguments fo EXinterrupt, which takes a nat.
- EXinterrupt takes a fourth argument EX_DELIVER. This was added for 6.1, but missed the printing of the spec.
- The argument array in the EX_ARGS structure is properly of type longnat, not of i4s. This matches the arguments actually provided to EXsignal.
- EXsys_report must now return TRUE for any CL raised exception. It previously only did so for those raised by hardware or the operating system. Now, exceptions generated internally by the CL must be treated the same way.
- The buffer handed to ERsys_report must be at least as big as the new EX_MAX_SYS_REP symbol.
- It has never been legal for a handler to EXCONTINUE from all exceptions. The conditions under which handlers may return EXCONTINUE are documented.
- All exceptions are documented for the first time.
- Some historically existing exceptions have been marked obsolescent. References to them in existing client code should be removed as opportunity permits.
- Some new exceptions have been added to handle the possibility of unrecoverable math problems on some platforms.
- A compile time flag, EX_HARD_MATH, has been added so client code may conditionally compile in handlers for the new unrecoverable math exceptions.
Specification
Introduction
EX is highly system and compiler dependent.
The usual method of handling errors in procedural languages such as C is for the called routine to pass failure information back to the caller, informing the caller of the manner of failure so that appropriate action may be taken. This is sometimes a cumbersome method to use in instances where a recoverable error may occur many routine levels below the routine which is capable of taking the appropriate recovery action, since every call along the chain will have to pass the information to a higher authority.
Errors can also be generated by the operating system / host hardware the program is running on, such as an attempted division by 0. Most operating systems have default actions for this type of error, usually termination of the running program. This may not be suitable, since the program may be able to back out the operation it has in progress, provide a user error message, and continue with the next operation. Even if aborting the program IS appropriate, there will very likely be cleanup that should take place before exit, such as removing temporary files, closing open files or databases, or restoring the mode of the users terminal.
The operating system may also wish to inform the program of outside events which aren't really errors at all, such as user interrupt keys which are caught by the OS, or completion of sub-processes. Or, the OS may signal errors that really have nothing to do with anything under control of the program, such as a signal indicating that the user's terminal was disconnected.
Library
CL
EX Mechanism
The point concerning OS generated errors and events is that they are asynchronous with normal program operation, and cannot easily be worked into the normal flow of control. Because we wish to have code portable across environments, there has to be an abstract mechanism used by the software to define how such asynchronous events are to be handled.
The mechanism is the EX module of the CL library. The basic idea is that a routine which knows how to handle exceptions calls EXdeclare, passing a handler routine which is to be called in the event of an exception, and a status block for saving context.
Arguments passed to an exception handler are packed into an EX_ARGS structure, which is defined as follows:
typedef struct
{
. . .
/* The number of arguments passed in exarg_array */
i4 exarg_count;
/* The number which identifies the exception */
EX exarg_num;
/* Optional arguments (as many as specified by exarg_count. */
i4 exarg_array[];
} EX_ARGS;
The maximum number of optional arguments passed to an exception handler is EX_MAX_ARGS (defined in ex.h). Generic code may assume that EX_MAX_ARGS is at least 4, but may not depend on EX_MAX_ARGS having a larger value.
When an exception is raised, either by software calling EXsignal or directly by the operating system, the handler is called as if by the following code:
{
# ifdef CL_HAS_PROTOS
(*handler)(EX_ARG * args);
# else
(*handler)();
# endif
EX_ARGS args;
STATUS status;
...
status = (*handler)(&args);
}
This scheme provides a way to back up several levels of routine calls, bypassing the normal return path. To do this, the software calls the EXsignal routine, which generates an exception to be handled as described above, exactly as if the operating system had asynchronously caused it at that point. The handler may cause a return to the point the handler was planted with EXdeclare. Other actions are also possible.
After executing some statements, the handler must return one of the following STATUS values to the calling exception mechanism. Each causes the exception mechanism to behave differently.
| EXCONTINUE. | Continue as if nothing had happened without executing any other exception handlers. This may only be done for exceptions that are documented to allow continuation. |
| EXRESIGNAL. | This tells the exception mechanism to look for another handler higher up the chain of calling routines, the next outer handler now getting its choice of actions. |
| EXDECLARE. | Return as if from the EXdeclare() call that declared this handler. This is nearly the same as asetjmp/longjmp call familiar to most C programmers. This transfers control back into the declaring routine. Unlike setjmp/longjmp, a handler returning EXDECLARE cause all intermediate handlers between it's context and the declaring context to be unwound. In terms of the declaring routine's control-flow, the EXdeclare call will normally return OK. If an exception occurs, and the handler routine indicates this action, it will seem that EXdeclare had returned an error status to the calling routine. |
Intermediate handlers being unwound are called with with the EX_UNWIND exception before return is made to the EXdeclare()-ed context. This gives them the chance to do some cleanup. The return value from a handler called with an EX_UNWIND is ignored. For clarity in the code, the handler should return EXRESIGNAL when called with an EX_UNWIND.
If an exception occurs in a handler (i.e. a nested exception), the mechanism continues the search after the last frame examined in the outer search. Thus no handler can be called to handle its own exceptions, unless it is done deliberately.
Exception numbers that may be raised by client code or internally by the CL are documented in a section below. Client code may only check the exception types that are listed. Exceptions are raised in software by calls to EXsignal(), which provides a variable argument list for any pertinent information to be passed to the handler through the EX_ARGS structure.
Restrictions and Warnings
EX users should understand the following restrictions and warnings.
- The routine calling EXdeclare() absolutely, positively must assure that EXdelete() is called once and only once before returning. Failure to do this can result in total havoc, as an exception may then restore the stack and generate a branch into an already returned function.
- All client testable exceptions must be registered in the CL specification.
- Client handlers may not use ifdefs to handle system dependant exceptions. They may only use the ones explicitly registered..
- Exceptions may only be tested using equality operators or through EXmatch. You may not use a switch because exceptions may be values that are illegal as case types on some machines.
- You may not make any assumptions about the contents of a routine's automatic variables after returning via EXdeclare. C does not say what variables might or might not be put in a register. Since registers may or may not have been restored in the return from deeper code, all locals are suspect.
- Only one handler may be active in a function at a time.
- It is an error to make two EXdeclare() within a function without an intervening EXdelete().
- If EXsignal is used to generate software exceptions, all code which calls it should be absolutely sure that it only executes under control of some higher routine which can handle the exception. This means that CL code linked into user programs should not raise exceptions unless it is positively planting its own top level handler.
- EXsignal can be called with a variable number of arguments. Remember to set the arg_count parameter to the correct number of optional arguments following arg_count, or to 0 if no optional arguments are used.
- Arguments expected by the handler, if any, must be passed.
- Handlers should check for the presence of expected arguments.
- The maximum number of optional arguments passed to an exception handler is EX_MAX_ARGS. EX_MAX_ARGS is guaranteed to be at least 4. Generic code may not depend on EX_MAX_ARGS having a value greater than 4.
- An unexpected exception may eventually reach a top level handler which aborts with some message like Undefined Exception. This is not a desirable action. The top level handler should make some better attempt to figure out what has happened. EXsys_report() is recommended.
- Exceptions inside exception handlers tend to lead to an infinite recursive chain of handler calls. Don't unconditionally call EXsignal under control of an exception handler, and be prepared for this behavior when debugging a handler.
Known Exceptions
Client code may only test for the exceptions listed here using EXmatch() or the equality operators == and !=. In addition to the documented exceptions, the CL may raise others that are known only to itself. All CL private exceptions will return TRUE when tested with EXsys_report().
In the tables that follow, Name is the name of the exception, defined in <ex.h>. Those marked with a * have delivery affected by EXinterrupt. Args lists mainline testable arguments, or unknown if the accompanying arguments are unknown at the CL interface. Continuable says whether or not it is legal to EXCONTINUE on receipt of the exception. If it is not continuable, the behaviour on an EXCONTINUE is undefined, and may result in process termination or an endless loop. Meaning explains what occurance of the exception indicates when raised by the CL. (Clients may always raise any exception listed here with EXsignal.)
You may not EXCONTINUE from an exception for which EXsys_report() returns TRUE, unless it is documented to be continuable. Undocumented exceptions raised by the CL, as determined with a call to EXsys_report(), may not be continued. Exceptions for which EXsys_report() returns FALSE may be continued.
The usual action in a handler when confronted with an unexpected exception would first be to call EXsys_report(). Then, either log the system provided message or one of its own, perform any necessary bcleanup, and return EXDECLARE, EXRESIGNAL or do some other exit.
The exceptions noted as obsolescent might exist and be raised by some CL implementations. Existing client code may now be checking for them explicitly, but this is almost always incorrect. They should be handled through the use of EXsys_report(). Future versions of the CL may remove their documentation and make their use in client code illegal.
The following exceptions are raised internally by the CL during the processing of another exception.
| General Exceptions Raised by the CL | ||||||
| Name | Args | Continuable? | Meaning | |||
|---|---|---|---|---|---|---|
| EX_UNWIND | Unknown | n/a | An unwind is in progress | |||
It is an error, with undefined results, for client code to raise EX_UNWIND. The handler return from an EXUNWIND exception is ignored. EXRESIGNAL is suggested as a return value.
The following exceptions may be raised by the CL and by client code. When raised by the CL, the meaning is as described.
| General Exceptions Raised by the CL | ||||||
| Name | Args | Continuable? | Meaning | |||
|---|---|---|---|---|---|---|
| EXINTR* | unknown | Yes | User interrupt | |||
| EXKILL | unknown | Yes | User termination | |||
User interrupt means the user caused some kind of stop operation event to occur, such as a CTRL-C on VMS, or a SIGINT on UNIX.
User termination is like a user interupt, only the user really wants it to happen now, with no questions asked.
The expectation is that an interrupt will leave the user in the current program, and a termination will make the program go away.
The following math exceptions may be raised by the CL or by client code. Clients may not rely on these being raised by the CL, as this is highly dependant on hardware support. Their generation may be affected by EXmath.
hard exceptions may not be delivered unless the symbol EX_HARD_MATH is defined in <ex.h>. Client code may have handlers that are only EXdeclare()-ed on machines with non-continuble exceptions, ifdef-ed with EX_HARD_MATH.
| Arithmetic Exception Registry | ||||||
| Name | Args | Continuable? | Meaning | |||
|---|---|---|---|---|---|---|
| EXDECOVF | unknown | Yes | Decimal overflow | |||
| EXDECDIV | unknown | Yes | Decimal divide-by-zero | |||
| EXFLTDIV | unknown | Yes | Float divide by 0 | |||
| EXFLTOVF | unknown | Yes | Float overflow | |||
| EXFLTUND | unknown | Yes | Float underflow | |||
| EXHFLTDIV | unknown | No | Hard float div. by 0 | |||
| EXHFLTOVF | unknown | No | Hard float overflow | |||
| EXHFLTUND | unknown | No | Hard float underflow | |||
| EXHINTDIV | unknown | No | Hard integer div by 0. | |||
| EXHINTOVF | unknown | No | Hard integer overflow. | |||
| EXINTDIV | unknown | Yes | Integer divide by 0 | |||
| EXINTOVF | unknown | Yes | Integer overflow | |||
| EXMNYDIV | unknown | Yes | Money divide by 0 | |||
| EXMNYOVF | unknown | Yes | Money overflow | |||
| MH_BADARG | unknown | No | Bad argument to MH routine | |||
| MH_INTERNERR | unknown | No | MH dryrot. | |||
| MH_MATHERR | unknown | No | MH dryrot. | |||
| MH_PRECISION | unknown | No | Bar return from MH routine | |||
The following exceptions are raised only by the mainline. They are registered here for information only. Their values may not conflict with other exceptions. Arguments are not interpreted by the CL, and may be used to pass information to the handler.
| Mainline Raised Exception Registry | ||||||
| Name | Args | Continuable? | Meaning | |||
|---|---|---|---|---|---|---|
| EXABFJMP | unknown | Yes | ? | |||
| EXCFJMP | unknown | Yes | ? | |||
| EXDIDBG | unknown | Yes | ? | |||
| EXEXIT | unknown | Yes | Exit program | |||
| EXFATER | unknown | Yes | ? | |||
| EXFEBUG | unknown | Yes | ? | |||
| EXFEMEM | unknown | Yes | ? | |||
| EXNOTEX | unknown | Yes | ? | |||
| EXOINCONS | unknown | Yes | ? | |||
| EXRDB_LJMP | unknown | Yes | ? | |||
| EXRWJMP | unknown | Yes | ? | |||
| EXTEEOF | unknown | Yes | ? | |||
| EXUNKNOWN | unknown | Yes | ? | |||
| EXVALJMP | unknown | Yes | ? | |||
| EXVFLJMP | unknown | Yes | ? | |||
| EXWINCONS | unknown | Yes | ? | |||
| EX_BT_LJMP | unknown | Yes | ? | |||
| EX_CM_LJMP | unknown | Yes | ? | |||
| EX_DMF_FATAL | unknown | Yes | ? | |||
| EX_JNP_LJMP | unknown | Yes | ? | |||
| EX_MON_LJMP | unknown | Yes | ? | |||
| EX_PSF_LJMP | unknown | Yes | ? | |||
Raising EXEXIT is intended to be give last-chance handlers an opportunity to run. If EXEXIT is continued, the EXsignal-ing code needs to do the PCexit.
The following obsolescent exception types may or may not exist and be raised in a particular CL implementation. Existing references in client code are not (yet) illegal, but the exception types are likely to disappear in the future.
Clients should examine any of their uses of these types. Current references are likely to be incorrect (EXsys_report should be used instead), semantically meaningless (what is an EX_OK exception?), or misguided (ME_00_ARG).
| Obsolete Exceptions | ||||||
| Name | Args | Continuable? | Meaning | |||
|---|---|---|---|---|---|---|
| EXBREAKQUERY | None | Yes | 5.0 query interrupt vestige | |||
| EXBUSERR | unknown | No | ? | |||
| EXCHLDDIED | unknown | Yes | Child process exited | |||
| EXCOMMFAIL | unknown | Yes | Communication failure | |||
| EXFLOAT | unknown | Yes | ? | |||
| EXKILLBACKEND | unknown | Yes | Synonym for EXKILL | |||
| EXQUIT* | unknown | Yes | Emphatic user interrupt | |||
| EXRESVOP | unknown | No | ? | |||
| EXSEGVIO | unknown | No | ? | |||
| EXTIMEOUT | unknown | Yes | Timer interrupt | |||
| EXTRACE | unknown | Yes | ? | |||
| EX_NO_FD | unknown | Yes | No more files may be opened | |||
| EX_OK | unknown | Yes | ? | |||
| ME_00_ARG | unknown | Yes | null ptr handed to ME. | |||
Notes on Interrupt Handling
Interrupts are generated asynchronously, either by users hitting a key or from another process. Some interrupt types are mapped into the EXINTR exception, others to EXKILL, others to CL private exceptions, and some might be eaten by the CL or ignored completely.
In the DBMS we are unconcerned about EXINTR, because there are never any sent to or received by the server. There is no appropriate action to be taken in the normal case. There may be some value to handling interrupts for debugging purposes, but in general they should be ignored by the server.
In frontends, however, we do need to pay attention. The handling of EXINTR, generated an user's asynchronous Control-C, causes potential re-entrancy problems. Code that is being interrupted by the signal might be re-entered from above and find itself in a scrambled state. In particular, on UNIX it is improper to start I/O on a file descriptor inside a signal handler that may be interrupting I/O. System calls are not re-entrant on UNIX.
The gotcha, for INGRES, is that an exception handler for EXINTR calls the libq IIbreak routine, which ends up calling GCsend, and ultimately rentering a read or write system call that got interrupted by the user's signal. In fact, this one of the most likely cases, as the user will hit control-C to give up a query that is taking too long, while GC is sitting in read waiting for an answer to come back from the server. (This ignores whatever renentrancy problems that GCA might have itself, keeping track of the state of the particular association.) The only way to avoid this problem is to prevent the completely asynchonous delivery of EXINTR at inconvenient times, while still guaranteeing that users can break out of delayed waits for a query response.
The correct way to do interrupt exception blocking is to use the EXinterrupt() call. EXinterrupt takes four arguments: EX_OFF, EX_ON, EX_DELIVER, and EX_RESET. Calls of EX_OFF bump a counter, and calls to EX_ON decrement it. When the counter is non-zero, the signal handler for SIGINT and SIGQUIT does not immediately raise the corresponding EXINTR or EXQUIT. Instead, it logs the occurace of the interrupt. If an EX_ON brings the block count to zero, and there are logged signals, the exceptions are raised. The counting feature allows code at different levels to insert EX_OFF/EX_ON calls in matched pairs without needing to worry about what code at some other level might be doing. Code that wants interrupts blocked will not find them surprisingly unblocked by lower level code. EX_RESET is a short cut that forces the count to zero and causes immediate delivery of the exceptions. EX_DELIVER exists to avoid a race condition between the arrival of an unwanted signal between an EX_ON and an EX_OFF. It causes immediate delivery of pending exceptions, but without changing the latch in the signal handler
(Archaeologists may unearth some obsolete interfaces, EXds_kbd_intrupt and EXen_kbd_intrupt. These completely turned the receipt of interrupts off and on without logging those that might have occured in a blind period. On UNIX, these do system calls, which is expensive. This is completely replaced by the better EXinterrupt mechanism.)
Header File <ex.h>
The header file <ex.h> must be included before using any of the functions provided. It defines all the exceptions types and handler return codes documented above, and the EX_ARGS structure already described. It also defines the following.
EX_CONTEXT - type used to define a handler context
The contents of this structure are unknown to client code.
typedef ... EX_CONTEXT;
EX_MAX_SYS_REP - length of buffer needed for EXsys_report
# define EX_MAX_SYS_REP
EX_MAX_ARGS - maximum number of optional arguments passed to handler
# define EX_MAX_ARGS
EX_MAX_ARGS is guaranteed to be at least 4. Generic code may not assume that EX_MAX_ARGS has a larger value.
Executable Interface
The following functions are provided.
EXdeclare - declare an exception handler in scope
Declare handler handle, a function returning one of the STATUS values EXCONTINUE, EXRESIGNAL, or EXDECLARE. Return OK if normal, return EXDECLARE if returning from an unwinding. The return value of EX_BADCONTEXT is returned if the context is not allocated locally in the current stack frame. One probably doesn't have to check for this error after debugging since it should never happen.
A function declaring a handler must remove it by calling EXdelete before returning. Client code must remove all handlers it declares. Failure to do so is a serious error.
Inputs:
| handle | The address of the handling function to install. |
| context | The address of a local EX_CONTEXT structure. |
Outputs:
| None |
Returns:
| OK | if operation succeeded, otherwise system specific error status. |
| EX_BADCONTEXT | |
| EXDECLARE | if the function appears to be exited by the handler's returning EXDECLARE. |
Definition:
STATUS EXdeclare(handle, context) STATUS (*handler)(); EX_CONTEXT *context;
EXdelete - delete an active exception handler
Delete the exception handler declared in the current call frame. EXdelete must be called before returning from a routine in which a handler is EXdeclare'd. EXdelete must not be called from a routine which does not have an active handler.
Inputs:
| None |
Outputs:
| None |
Returns:
| None |
Definition:
VOID EXdelete()
EXinterrupt - Alter delivery of user generated exceptions
Controls delivery of normal user originated exceptions. This includes EXINTR. These come at completely random times as generated by a user at the keyboard. The value of new_state must be one of EX_OFF, EX_ON, EX_RESET, or EX_DELIVER. By default, exceptions are delivered immediately.
- EX_OFF means you don't want to receive these exceptions when they are triggered. It bumps a level count and has EX log the exceptions as pending.
- EX_ON decrements the level count set by EX_OFF, and if it is 0, delivers any pending exceptions.
- EX_RESET forces the level count to 0, and delivers any pending exceptions.
- EX_DELIVER causes delivery of any pending exceptions without adjusting the level count. This lets you poll for pending keyboard exceptions without opening a window of vulnerability to their asynchronous delivery.
Inputs:
| new_state | one of EX_OFF, EX_ON, EX_RESET, or EX_DELIVER, as described above. |
Outputs:
| None |
Returns:
| None |
Definition:
VOID EXinterrupt(new_state) i4 new_state;
EXmatch - match exception values
Given an exception, ex, it searches for it as a member of its argument list. It returns the index of the matching exception number, or it returns zero to signify that none matched. Switch on the returned index to handle specific exceptions.
This routine is necessary because the EX exception type is an illegal case label in a switch in some environments.
Inputs:
| ex | The exception in question. |
| arg_count | The number of following arguments |
| ex_match1 ... | Values to compare against the input exception. |
Outputs:
| None |
Returns:
| Index into the list of the matched exception (starting at 1), or 0 if no match was found in the list. |
Definition:
i4 EXmatch(ex, arg_count, ex_match1, ex_match2, ...) EX ex; i4 arg_count; EX ex_match1; EX ex_match2;
EXmath - Enable/Disable some math exceptions
Attempt to enable (or disable) the generation of math exceptions, such as EXDECOVF, EXFLTUND, EXINTOVF, cancelling effect of any previous EXmath() calls. On VMS, these exceptions are ENABLED by default. New_state must be either EX_ON or EX_OFF.
The affect of this routine will vary from machine to machine. It provides a hint about the behaviour the client would prefer. Some machines may never generate exceptions for exceptional math conditions, and on other machines it may be impossible to turn them off.
If the hard math exceptions may be raised on a system, from which continuation is illegal, the compile time flag EX_HARD_MATH will be defined. This allows placement of additional handlers that may be needed.
Inputs:
| new_state | one either EX_ON or EX_OFF, as described above. |
Outputs:
| None |
Returns:
| None |
Definition:
VOID EXmath(new_state) i4 new_state;
EXsignal - raise exception
Signal exception ex with handler arguments arg1, arg2 .... It is critical that arg_count is correct.
The maximum number of optional arguments passed to EXsignal is EX_MAX_ARGS. EX_MAX_ARGS is guaranteed to be at least 4. Generic code may not assume that EX_MAX_ARGS is greater than 4.
The calling routine must behave responsibly if the exception is blindly continued with no action by the handler. It may not loop on an error condition assuming that the handler will clear it making continuation possible.
Inputs:
| ex | the exeception to raise. |
| arg_count | The number of following arguments, must be less than or equal to EX_MAX_ARGS. |
| "arg1 ..." | Arguments to be passed to the handler functions. |
Outputs:
| None |
Returns:
| None |
| May not return if a handler returns EXDECLARE. |
Definition:
VOID EXsignal(ex, arg_count, arg1, ...) EX ex; i4 arg_count; i4 arg1; i4 arg2;
EXsys_report - Report System/Hardware/CL Exceptions
Reports if an exception was generated by hardware, the operating system, or internally by the CL. When this is the case, an appropriate message is copied into the buffer and TRUE is returned. Otherwise, FALSE is returned.
An exception for which EXsys_report returns TRUE may not be continued, unless documented otherwise. Exceptions for which EXsys_report returns FALSE may be continued.
Buffer may be NULL, in which case no diagnostic message output will be available.
The buffer must be at least EX_MAX_SYS_REP in length.
Inputs:
| exarg | The exception argument structure to decode. |
Outputs:
| buffer | The address of the buffer that can contain the message for the hardware/system execption. |
Returns:
| FALSE | if the exception was not raised within the CL or by hardware or the operating system. |
Definition:
bool EXsys_report (exargs, buffer) EX_ARGS *exargs; char *buffer;
Examples
This example shows the correct way to declare and use an exception handler.
STATUS handler(); /* handler routine */
STATUS
proc()
{
EX_CONTEXT ex; /* context for stack recovery */
STATUS ret_val;
ret_val = OK;
if ( EXdeclare(handler, &ex) != OK )
{
/* code to handle those exceptions for
** which handler() will return EXDECLARE
*/
/* assuming we wish to exit this procedure we set
** ret_val to FAIL. If we wish to re-run this procedure,
** we would leave ret_val set at OK. Note that re-running
** the procedure in this way we still have the handler
** setup.
*/
ret_val = FAIL;
}
if (ret_val == OK)
{
/* ... main body of procedure ... */
}
EXdelete(); /* This MUST be done before returning */
return (ret_val);
}
STATUS
handler(ex_args)
EX_ARGS *ex_args;
{
char msg[ EX_MAX_SYS_REP ];
/* examine ex_args to determine the nature of the exception,
** and return EXRESIGNAL, EXCONTINUE or EXDECLARE for
** bump up to next handler, ignore or transfer control
** to EXdeclare() caller
*/
if( ex_args->exarg_num == EX_the_one_to_continue )
return( EXCONTINUE );
else if( EXsys_report( ex_args, msg ) )
{
TRdisplay("%s", msg );
}
else
{
TRdisplay("Unexpected exception 0x%x\n", ex_args->exarg_num);
}
return EXDECLARE;
}
|
Ingres Compatability Library |
