使用取消处理程序

注: 有关使用 try-catch-throw 功能的信息,请参阅 ILE C/C++ Language Reference。
可以在函数中的代码主体周围启用取消处理程序。 启用取消处理程序时,仅当调用堆栈条目的暂挂点在该代码中 (在 #pragma cancel_handler 和 #pragma disable_handler 伪指令中) ,并且调用堆栈条目已取消时,才会进行控制。
#pragma cancel_handler 伪指令提供了一种在调用堆栈条目 (或调用堆栈条目中的暂挂点) 中静态注册取消处理程序的方法。 "注册调用堆栈入口终止用户出口过程" (CEERTX) 和 "注销调用堆栈入口终止用户出口过程" (CEETUTX) ILE 可绑定 API 提供了一种方法来动态注册要在其注册的调用堆栈入口取消时执行的用户定义例程。
取消处理程序通过允许您在调用堆栈条目以非正常返回结束时控制清除和恢复操作来提供重要功能。
在 #pragma cancel_handler 伪指令上,指定了取消处理程序例程 (绑定 ILE 过程) 的名称以及用户定义的通信区域。 通过通信区域,将信息从应用程序传递到处理程序函数。 调用取消处理程序函数时,将向其传递指向 <except.h> 头文件中定义的类型为 _CNL_Hndlr_Parms_T 的结构的指针。 此结构除了包含系统传递的一些其他有用信息外,还包含指向通信区域的指针。 此附加信息包含取消呼叫的原因。
示例:
以下简单示例说明了 ILE 取消处理程序机制的使用。 此功能允许应用程序有机会调用用户提供的函数,以在取消特定函数调用时执行诸如错误报告和日志记录,关闭文件等操作。 导致发生取消的通常方法是: 使用 exit() 函数或 abort() 函数,使用 longjmp() 函数跳至较早的调用,并从未处理的异常生成 CEE9901 函数检查。
#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 runtime 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 runtime 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'... */
/*-------------------------------------------------------------------*/