ILE C/C++ Programmer's Guide


Using Cancel Handlers


C++ language only
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 ]