ILE C/C++ Programmer's Guide

Cancel handlers are used by C++ to call destructors during stack
unwinding. It is recommended that you use the C++ try-catch-throw
feature to ensure objects are destructed properly.
- Note:
- For information about using the try-catch-throw feature, see WebSphere Development Studio: ILE C/C++ Language
Reference.
A cancel handler may be enabled around a body of code inside a
function. When a cancel handler is enabled it only gets control if the
suspend point of the call stack entry is inside that code (within the
#pragma cancel_handler and #pragma disable_handler
directives), and the call stack entry is cancelled.
The #pragma cancel_handler directive provides a way to statically
register a cancel handler within a call stack entry (or suspend point within a
call stack entry). The Register Call Stack Entry Termination User Exit
Procedure (CEERTX) and the Unregister Call Stack Entry Termination User Exit
Procedure (CEETUTX) ILE bindable APIs provide a way of dynamically registering
a user-defined routine to be executed when the call stack entry for which it
is registered is cancelled.
Cancel handlers provide an important function by allowing you to get
control for clean-up and recovery actions when call stack entries are ended by
something other than a normal return.
On the #pragma cancel_handler directive, the name of the cancel
handler routine (a bound ILE procedure) is specified, along with a
user-defined communications area. It is through the communications area
that information is passed from the application to the handler
function. When the cancel handler function is called, it is passed a
pointer to a structure of type _CNL_Hndlr_Parms_T which
is defined in the <except.h> header file. This
structure contains a pointer to the communications area in addition to some
other useful information that is passed by the system. This additional
information includes the reason why the call was cancelled.
Example:
The following simple example illustrates the use of the ILE Cancel Handler
mechanism. This capability allows an application the opportunity to
have a user-provided function called to perform things such as error reporting
and logging, closing of files, etc. when a particular function
invocation is cancelled. The usual ways that cause cancelation to occur
are: using the exit() function or the abort()
function, using the longjmp() function to jump to an earlier call
and having a CEE9901 Function Check generated from an unhandled
exception.
Figure 185. T1520XH4 -- ILE C Source that Uses Cancel Handlers
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <except.h>
/*-------------------------------------------------------------------*/
/* The following function is called a "cancel handler". It is */
/* registered for a particular invocation (function) with the */
/* #pragma cancel_handler directive. The variable identified */
/* on this directive as the "communications area" can be accessed */
/* using the 'Com_Area' member of the _CNL_Hndlr_Parms_T structure. */
/* */
/*-------------------------------------------------------------------*/
void CancelHandlerForReport( _CNL_Hndlr_Parms_T *cancel_info ) {
printf("In Cancel Handler for function 'Report' ...\n");
/* Changing the value in the communications area will update the */
/* 'return_code' variable in the invocation being cancelled */
/* (in function 'Report' in this example). Note that the */
/* ILE C compiler will issue a warning for the following */
/* statement since it uses a non-ISO C compliant technique. */
/* However, this will not affect the expected run-time behavior. */
/* Set "return_code" in Report to an arbitrary number. */
*( (volatile unsigned *)cancel_info->Com_Area ) = 500;
printf("Communication Area now has the value: %d \n",
*( (volatile unsigned *)cancel_info->Com_Area) );
printf("Leaving Cancel Handler for function 'Report'...\n");
}
/*-------------------------------------------------------------------*/
/* The following function is also called a cancel handler but has */
/* been registered for the 'main' function. That is, when the */
/* 'main' function is cancelled, this function will automatically */
/* be called by the system. */
/* */
/*-------------------------------------------------------------------*/
void CancelHandlerForMain( _CNL_Hndlr_Parms_T *cancel_info ) {
printf("In Cancel Handler for function 'main' ...\n");
/* Changing the value in the communications area will update the */
/* 'return_code' variable in the invocation being cancelled */
/* (in function 'main' in this example). Note that the */
/* ILE C compiler will issue a warning for the following */
/* statement since it uses a non-ISO C compliant technique. */
/* However, this will not affect the expected run-time behavior. */
/* Set "return_code" in main to an arbitrary number. */
*( (volatile unsigned *)cancel_info->Com_Area ) = 999;
printf("Communication Area now has the value: %d \n",
*( (volatile unsigned *)cancel_info->Com_Area) );
printf("Leaving Cancel Handler for function 'main'...\n");
}
/*-------------------------------------------------------------------*/
/* The following is simple function that registers another function */
/* (named 'CancelHandlerForReport' in this example) as its "cancel */
/* handler". When 'exit()' is used from this function, then this */
/* invocation and all prior invocations are cancelled by the system */
/* and any registered cancel handlers functions are automatically */
/* called. */
/*-------------------------------------------------------------------*/
void Report( void ) {
volatile unsigned return_code; /* communications area */
#pragma cancel_handler( CancelHandlerForReport, return_code )
printf("in function Report()...about to call 'exit'...\n");
/* Using the exit function will cause this function invocation */
/* and all function invocations within this program to be */
/* cancelled. If any of the functions being cancelled have */
/* cancel handlers enabled, then those cancel handler functions */
/* will be called by the system after each cancellation. */
exit( 99 ); /* exit with an arbitrary value */
printf("in function Report() just after calling 'exit'... \n");
#pragma disable_handler
}
/*-------------------------------------------------------------------*/
/* In the 'main()' function a cancel handler is registered so that */
/* the function 'CancelHandlerForMain()' is called if 'main()' is */
/* cancelled. */
/*-------------------------------------------------------------------*/
int main( void ) {
volatile unsigned return_code; /* communications area */
#pragma cancel_handler( CancelHandlerForMain, return_code )
return_code = 0; /* initialize return code which will */
/* eventually be set in the cancel handler */
printf("In main() about to call Report()...\n");
Report();
printf("...back from calling Report(). \n");
printf("return_code = %d \n", return_code );
#pragma disable_handler
}
/*-------------------------------------------------------------------*/
/* This program will result in the following screen output: */
/* */
/* In main() about to call Report()... */
/* in function Report()...about to call 'exit'... */
/* In Cancel Handler for function 'Report' ... */
/* Communication Area now has the value: 500 */
/* Leaving Cancel Handler for function 'Report'... */
/* In Cancel Handler for function 'main' ... */
/* Communication Area now has the value: 999 */
/* Leaving Cancel Handler for function 'main'... */
/*-------------------------------------------------------------------*/
|
[ Top of Page | Previous Page | Next Page | Table of Contents ]
(C) Copyright IBM Corporation 1992, 2005. All Rights Reserved.