2054 lines
74 KiB
Text
2054 lines
74 KiB
Text
|
\input texinfo @c -*-texinfo-*-
|
||
|
|
||
|
@c $Id: chf.texi,v 2.2 2001/01/25 12:06:29 cibrario Exp $
|
||
|
@c %**start of header
|
||
|
@setfilename chf.info
|
||
|
@settitle Chf library (libChf r2.2) Documentation
|
||
|
@setchapternewpage on
|
||
|
@iftex
|
||
|
@afourpaper
|
||
|
@end iftex
|
||
|
@c %**end of header
|
||
|
|
||
|
@ifinfo
|
||
|
This manual documents the Condition Handling Facility library (libChf r2.2).
|
||
|
|
||
|
The Chf library provides a centralized, unified method of generating and
|
||
|
signaling exceptional conditions, establishing exception handlers, and
|
||
|
printing status and error messages.
|
||
|
@end ifinfo
|
||
|
|
||
|
@titlepage
|
||
|
@title CHF library Documentation
|
||
|
@subtitle Condition Handling Facility library
|
||
|
@subtitle (libChf r2.2)
|
||
|
@author Ivan Cibrario B.
|
||
|
@end titlepage
|
||
|
|
||
|
@node Top, Overview, (dir), (dir)
|
||
|
|
||
|
@ifinfo
|
||
|
This manual describes the Condition Handling Facility library, and
|
||
|
applies to its release 2.2.
|
||
|
@end ifinfo
|
||
|
|
||
|
@menu
|
||
|
* Overview::
|
||
|
* Initialization and exit::
|
||
|
* Condition generation and signal::
|
||
|
* General condition handling::
|
||
|
* Structured condition handling::
|
||
|
* Chf conditions::
|
||
|
* Message retrieval::
|
||
|
* Multithreading support::
|
||
|
* Other useful macro definitions::
|
||
|
* Other useful functions::
|
||
|
* Changes since release 1::
|
||
|
* Changes since release 2.1::
|
||
|
* Function Index::
|
||
|
* Data Type Index::
|
||
|
* Concept Index::
|
||
|
|
||
|
@c @detailmenu --- The Detailed Node Listing ---
|
||
|
|
||
|
Initialization and exit
|
||
|
|
||
|
* ChfInit()::
|
||
|
* ChfMsgcatInit()::
|
||
|
* ChfStaticInit()::
|
||
|
* ChfWin32Init()::
|
||
|
* ChfExit()::
|
||
|
* ChfAbort()::
|
||
|
* Library header::
|
||
|
|
||
|
Condition generation and signal
|
||
|
|
||
|
* Generating a condition::
|
||
|
* Signaling a condition::
|
||
|
|
||
|
Generating a condition
|
||
|
|
||
|
* ChfCondition::
|
||
|
* ChfEnd::
|
||
|
* ChfSeverity::
|
||
|
* ChfErrnoCondition::
|
||
|
|
||
|
Signaling a condition
|
||
|
|
||
|
* ChfSignal()::
|
||
|
|
||
|
Condition handling
|
||
|
|
||
|
* Condition handlers::
|
||
|
* Condition descriptors::
|
||
|
* Condition handling state::
|
||
|
* Handler actions::
|
||
|
* Default handler::
|
||
|
|
||
|
Condition handlers
|
||
|
|
||
|
* ChfHandler::
|
||
|
* ChfPushHandler()::
|
||
|
* ChfPopHandler()::
|
||
|
|
||
|
Structured condition handling
|
||
|
|
||
|
* Syntax of structured condition handlers::
|
||
|
* Chf behavior during structured condition handling::
|
||
|
|
||
|
Chf behavior during structured condition handling
|
||
|
|
||
|
* ChfTry::
|
||
|
* ChfCatch::
|
||
|
* ChfEndTry::
|
||
|
|
||
|
Message retrieval
|
||
|
|
||
|
* Retrieving a message::
|
||
|
* Reserved module identifiers::
|
||
|
* Defining a new message retrieval subsystem::
|
||
|
|
||
|
Retrieving a message
|
||
|
|
||
|
* ChfGetMessage()::
|
||
|
* ChfBuildMessage()::
|
||
|
|
||
|
@c @end detailmenu
|
||
|
@end menu
|
||
|
|
||
|
@node Overview, Initialization and exit, Top, Top
|
||
|
@chapter Overview
|
||
|
@cindex Overview
|
||
|
@cindex Win32 Support
|
||
|
|
||
|
The Condition Handling facility library
|
||
|
provides a centralized, unified method of generating and
|
||
|
signaling exceptional conditions. This method can be used either in
|
||
|
conjunction with, or in alternative to, the traditional style of handling
|
||
|
error conditions by returning distinguished error values when an error
|
||
|
occurs in a procedure, and checking for these values after each procedure
|
||
|
invocation.
|
||
|
|
||
|
It serves many different purposes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
It helps to gather and make available as much information as possible when
|
||
|
an error occurs, such as which source module detected it, its severity,
|
||
|
and any other ancillary information the user may find useful.
|
||
|
|
||
|
@item
|
||
|
It provides an unified method to log and print error messages, and to
|
||
|
internationalize applications.
|
||
|
|
||
|
@item
|
||
|
By means of condition handlers, it gives the user a convenient way to
|
||
|
implement global exception recovery actions in an application.
|
||
|
|
||
|
@item
|
||
|
It may improve the readability of the source code, because less explicit
|
||
|
checks for error conditions are required.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
Since release @code{2.2}, the Chf library also supports Unicode-based Win32
|
||
|
systems, notably Windows CE. Implementation details of the Win32 version
|
||
|
of the library will be discussed in the documentation, and will be
|
||
|
highlighted by the @strong{Win32} keyword. Moreover, the following
|
||
|
general notes apply:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
All library functions, when compiled for Win32, handle Unicode
|
||
|
character strings (array of @code{TCHAR}) instead of ASCII strings
|
||
|
(array of @code{char}); this change is transparent and the documentation
|
||
|
does not reflect it.
|
||
|
|
||
|
@item
|
||
|
Library functions @code{sigsetjmp()} and @code{siglongjmp()} are not
|
||
|
supported; accordingly, they are replaced by
|
||
|
@code{setjmp()} and @code{longjmp()}. The non-local control transfer
|
||
|
context buffer, @code{sigjmp_buf} is also replaced by @code{jmp_buf};
|
||
|
this change is transparent and the documentation does not reflect it.
|
||
|
|
||
|
@item
|
||
|
The reentrant flavor of the Chf library is not yet supported. Multithreaded
|
||
|
application must serialize Chf accesses themselves.
|
||
|
|
||
|
@item
|
||
|
The @code{ChfErrnoCondition} macro is not supported, and has no effect.
|
||
|
|
||
|
@item
|
||
|
The default condition handler does not display the condition message
|
||
|
on the standard error stream.
|
||
|
|
||
|
@item
|
||
|
The @code{CHF_ABORT} initialization flag is not fully supported;
|
||
|
when used, the Chf library invokes @code{exit(EXIT_FAILURE)}
|
||
|
instead of @code{abort()} (not supported by Win32) to abort the application.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
The following terms will be used often throughout this document:
|
||
|
|
||
|
@table @code
|
||
|
@item Exception
|
||
|
@cindex Exception
|
||
|
An @dfn{exception} is an event that changes the normal flow of instruction
|
||
|
execution, and is usually caused by an error condition. Any procedure can
|
||
|
generate an exception using the @code{ChfGenerate} macro, and then
|
||
|
raise or signal it using the @code{ChfSignal()} function call.
|
||
|
|
||
|
@item Condition
|
||
|
@cindex Condition
|
||
|
An informational state which exists when an exception occurs, and encloses
|
||
|
information about the exception itself. The term @dfn{condition} is preferred,
|
||
|
since the term exception usually implies an error.
|
||
|
|
||
|
@item Condition handling
|
||
|
@cindex Condition handling
|
||
|
When a condition is detected during the execution of a procedure, the
|
||
|
procedure can signal the condition. The
|
||
|
hierarchy of currently active condition handlers is then permitted to
|
||
|
respond to the condition; the procedure response is called
|
||
|
@dfn{condition handling}.
|
||
|
|
||
|
The condition handlers are themselves procedures and they are called
|
||
|
with the usual calling conventions; the only exception is that, in the
|
||
|
current release of the Chf library, they cannot establish condition
|
||
|
handlers of their own.
|
||
|
|
||
|
A procedure can establish a condition handler using the function
|
||
|
@code{ChfPushHandler()}, that pushes a new condition handler on top of
|
||
|
a LIFO handler stack; the condition handler stays active until a
|
||
|
matching call to @code{ChfPopHandler()}, that pops the topmost handler
|
||
|
from the handler stack is executed, or until an execution stack
|
||
|
unwind occurs.
|
||
|
|
||
|
Another way to implicitly establishing and removing condition handlers
|
||
|
is to use the structured condition handling macros.
|
||
|
@xref{Structured condition handling}, for more information.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node Initialization and exit, Condition generation and signal, Overview, Top
|
||
|
@chapter Initialization and exit
|
||
|
@cindex Initialization and exit
|
||
|
@cindex Initialization
|
||
|
@cindex Exit
|
||
|
|
||
|
Before using any function of the Chf library, it must be correctly
|
||
|
initialized. Since the library has a generic interface towards the
|
||
|
message retrieval subsystem (@pxref{Message retrieval}),
|
||
|
more than one initialization function exist, one each for every message
|
||
|
retrieval subsystem the library supports, plus one custom initialization
|
||
|
function to use if a custom message retrieval subsystem is used.
|
||
|
After initialization, the library accesses the message retrieval subsystem
|
||
|
transparently, and its peculiarities are no longer visible to the users.
|
||
|
|
||
|
All initialization functions, when successful, register a default condition
|
||
|
handler. @xref{Default handler}.
|
||
|
|
||
|
Moreover, each module using the Chf library must include the header file
|
||
|
@code{Chf.h} and provide some basic definitions. @xref{Library header}.
|
||
|
|
||
|
@menu
|
||
|
* ChfInit()::
|
||
|
* ChfMsgcatInit()::
|
||
|
* ChfStaticInit()::
|
||
|
* ChfWin32Init()::
|
||
|
* ChfExit()::
|
||
|
* ChfAbort()::
|
||
|
* Library header::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfInit(), ChfMsgcatInit(), Initialization and exit, Initialization and exit
|
||
|
@section ChfInit()
|
||
|
@cindex Initialization
|
||
|
@deftypefn Function int ChfInit (const char *app_name, const ChfOptions options, void *mrs_data, ChfMrsGet mrs_get, ChfMrsExit mrs_exit, const int condition_stack_size, const int handler_stack_size, const int exit_code)
|
||
|
|
||
|
This function initializes the Chf library using a custom message retrieval
|
||
|
subsystem, and returns to the caller a condition code; that code will be either
|
||
|
@code{CHF_S_OK} if the initialization was successful, or one of the other
|
||
|
values listed below.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item app_name
|
||
|
is the name of the application. It can be used by condition
|
||
|
handlers to print out error messages.
|
||
|
|
||
|
@item options
|
||
|
is the bitwise or of the following option identifiers:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_DEFAULT
|
||
|
Represents the default value for all options.
|
||
|
|
||
|
@item CHF_ABORT
|
||
|
If this flag is set, the Chf library will use @code{abort()} instead of
|
||
|
either @code{exit(exit_code)} or @code{pthread_exit(exit_code)} to abort
|
||
|
the application when an unrecoverable exception occurs. This forces a
|
||
|
core dump that may be useful for debugging purposes.
|
||
|
|
||
|
@strong{Win32:} This flag is not fully supported; the Chf library
|
||
|
invokes @code{exit(EXIT_FAILURE)} instead of @code{abort()} (not
|
||
|
supported by Win32) to abort the application.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@item mrs_data
|
||
|
Private data pointer for the custom message retrieval subsystem.
|
||
|
|
||
|
@item mrs_get
|
||
|
Message retrieval subsystem's 'Get Message' function.
|
||
|
|
||
|
@item mrs_exit
|
||
|
Message retrieval subsystem's 'Exit' function.
|
||
|
|
||
|
@item condition_stack_size
|
||
|
Size of the condition stack. This value determines the maximum number of
|
||
|
pending conditions, i.e. conditions that have been generated but have
|
||
|
not been signaled yet. A condition that is being signaled is
|
||
|
still pending until the signaling sequence completes.
|
||
|
|
||
|
@item handler_stack_size
|
||
|
Size of the handler stack. This value determines the maximum number of
|
||
|
active condition handlers the application can have. A condition handler is
|
||
|
activated when a @code{ChfPushHandler()} is executed for it, and it is
|
||
|
deactivated when the corresponding @code{ChfPopHandler()} completes.
|
||
|
In addition, each execution of the @code{ChfTry} macro also pushes
|
||
|
a condition handler; the handler is removed when @code{ChfEndTry}
|
||
|
is executed.
|
||
|
|
||
|
@item exit_code
|
||
|
This is the exit code the Chf library will use to exit either the
|
||
|
application or the offending thread when an unrecoverable exception
|
||
|
occurs.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Return values:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_S_OK
|
||
|
The Chf library has been successfully initialized.
|
||
|
|
||
|
@item CHF_F_MALLOC
|
||
|
Dynamic memory allocation failed during initialization.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
It's necessary to invoke successfully @code{ChfInit()}, either directly
|
||
|
or indirectly, through another Chf initialization function, before using
|
||
|
any other Chf function; otherwise, they will either fail and abort the
|
||
|
application (when multithreading support is not enabled), or have
|
||
|
unpredictable results (when multithreading support is enabled).
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code
|
||
|
@code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized
|
||
|
before. Notice that when multithreading support is enabled, @code{ChfInit()}
|
||
|
must be invoked only once before starting multithreaded operation.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfMsgcatInit(), ChfStaticInit(), ChfInit(), Initialization and exit
|
||
|
@section ChfMsgcatInit()
|
||
|
@cindex Initialization
|
||
|
@cindex Internationalization
|
||
|
@deftypefn Function int ChfMsgcatInit (const char *app_name, const ChfOptions options, const char *msgcat_name, const int condition_stack_size, const int handler_stack_size, const int exit_code)
|
||
|
|
||
|
This function initializes the Chf library and activates the message retrieval
|
||
|
subsystem based on @code{catgets()}, offering support for
|
||
|
text-based internationalized applications.
|
||
|
|
||
|
The argument @code{msgcat_name} is the name of the application/locale
|
||
|
specific message catalog to be used to retrieve the messages. The other
|
||
|
arguments have the meaning already described for @code{ChfInit()},
|
||
|
@xref{ChfInit()}.
|
||
|
|
||
|
@strong{Win32:} This function is not supported and always returns
|
||
|
@code{CHF_F_NOT_AVAILABLE}.
|
||
|
|
||
|
Return values:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_S_OK
|
||
|
The Chf library has been successfully initialized.
|
||
|
|
||
|
@item CHF_F_SETLOCALE
|
||
|
the @code{setlocale()} function has failed during initialization.
|
||
|
|
||
|
@item CHF_F_CATOPEN
|
||
|
the @code{catopen()} function has failed and therefore the message catalog was
|
||
|
not opened.
|
||
|
|
||
|
@item CHF_F_MALLOC
|
||
|
Dynamic memory allocation failed during initialization.
|
||
|
|
||
|
@item CHF_F_NOT_AVAILABLE
|
||
|
Function not available on current platform.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
It's necessary to invoke successfully either @code{ChfMsgcatInit()},
|
||
|
or another Chf initialization function described in this chapter,
|
||
|
before using any other Chf function.
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code
|
||
|
@code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized
|
||
|
before.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfStaticInit(), ChfWin32Init(), ChfMsgcatInit(), Initialization and exit
|
||
|
@section ChfStaticInit()
|
||
|
@cindex Initialization
|
||
|
@deftypefn Function int ChfStaticInit (const char *app_name, const ChfOptions options, const ChfTable *table, const size_t table_size, const int condition_stack_size, const int handler_stack_size, const int exit_code)
|
||
|
|
||
|
This function initializes the Chf library and activates the static
|
||
|
message retrieval subsystem using the message table @code{table},
|
||
|
of @code{table_size} elements. This is the simplest message retrieval
|
||
|
subsystem currently supported, and supports applications that must work
|
||
|
with minimal operating system assistance.
|
||
|
|
||
|
Return values:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_S_OK
|
||
|
The Chf library has been successfully initialized.
|
||
|
|
||
|
@item CHF_F_MALLOC
|
||
|
Dynamic memory allocation failed during initialization.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
It's necessary to invoke successfully either @code{ChfStaticInit()},
|
||
|
or another Chf initialization function described in this section,
|
||
|
before using any other Chf function.
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code
|
||
|
@code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized
|
||
|
before.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftp {Data type} ChfTable
|
||
|
@cindex Standalone message table
|
||
|
This data type is a structure representing an element of a standalone message
|
||
|
table, to be used with the static message retrieval subsystem. Each table
|
||
|
element associates a pair (@code{module_id}, @code{code}) with a message
|
||
|
fragment or template. It has the following fields:
|
||
|
|
||
|
@table @code
|
||
|
@item int module
|
||
|
The module identifier of the message fragment to be defined.
|
||
|
|
||
|
@item int code
|
||
|
The condition code of the message fragment to be defined.
|
||
|
|
||
|
@item char *msg_template
|
||
|
The message fragment or template associated with
|
||
|
(@code{module_id}, @code{code}).
|
||
|
|
||
|
@end table
|
||
|
@end deftp
|
||
|
|
||
|
@node ChfWin32Init(), ChfExit(), ChfStaticInit(), Initialization and exit
|
||
|
@section ChfWin32Init()
|
||
|
@cindex Initialization
|
||
|
@cindex Internationalization
|
||
|
@deftypefn Function int ChfWin32Init (const char *app_name, const ChfOptions options, HINSTANCE instance, const int condition_stack_size, const int handler_stack_size, const int exit_code)
|
||
|
|
||
|
This function initializes the Chf library and activates the message
|
||
|
retrieval subsystem based on the Win32 function @code{LoadString()},
|
||
|
offering limited support for Win32 internationalized applications.
|
||
|
|
||
|
This function does not support message sets, so the linear message id
|
||
|
passed to it is made by @code{module_id*1000 + condition_code}.
|
||
|
|
||
|
The @code{instance} argument is the handle of the calling application
|
||
|
instance; it will be used as an argument to @code{LoadString()}. All
|
||
|
other arguments have the meaning already described for @code{ChfInit()},
|
||
|
@xref{ChfInit()}.
|
||
|
|
||
|
@strong{Win32:} This function is supported on Win32 only, and always
|
||
|
returns @code{CHF_F_NOT_AVAILABLE} when invoked on Unix platforms.
|
||
|
Notice also that on Win32 the @code{ChfAbort()} function will be able to
|
||
|
print out the abort message only if Chf has been initialized correctly
|
||
|
and the @code{GetActiveWindow()} function yields a valid window handle
|
||
|
when @code{ChfAbort()} is invoked.
|
||
|
|
||
|
Return values:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_S_OK
|
||
|
The Chf library has been successfully initialized.
|
||
|
|
||
|
@item CHF_F_MALLOC
|
||
|
Dynamic memory allocation failed during initialization.
|
||
|
|
||
|
@item CHF_F_NOT_AVAILABLE
|
||
|
Function not available on current platform.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
It's necessary to invoke successfully either @code{ChfWin32Init()},
|
||
|
or another Chf initialization function described in this chapter,
|
||
|
before using any other Chf function.
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code
|
||
|
@code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized
|
||
|
before.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfExit(), ChfAbort(), ChfWin32Init(), Initialization and exit
|
||
|
@section ChfExit()
|
||
|
@cindex Exit
|
||
|
@deftypefn Function void ChfExit (void)
|
||
|
|
||
|
This function shuts down the Chf library and returns nothing to the caller;
|
||
|
after calling @code{ChfExit()} the application can continue, but any
|
||
|
subsequent call to other Chf functions,
|
||
|
except to the initialization functions, will either abort
|
||
|
the application using @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
(when multithreading support is not enabled) or have unpredictable results
|
||
|
(when multithreading support is enabled).
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
if Chf hasn't been initialized yet.
|
||
|
|
||
|
@item
|
||
|
When multithreading support is enabled, it is responsibility of the
|
||
|
application designer to ensure that no other Chf functions,
|
||
|
except initialization functions, will be
|
||
|
called after this function has been.
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfAbort(), Library header, ChfExit(), Initialization and exit
|
||
|
@section ChfAbort()
|
||
|
@cindex Abort
|
||
|
@deftypefn Function void ChfAbort (const int abort_code)
|
||
|
This function prints the message associated with @code{abort_code} and
|
||
|
then immediately aborts either the application or the invoking
|
||
|
thread. The abort is performed either:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
using @code{abort()} if either Chf has not been correctly initialized
|
||
|
yet, or the Chf option flag @code{CHF_ABORT} has been set during
|
||
|
initialization. Since this is mainly intended to be a debugging aid,
|
||
|
@code{abort()} is used whether or not multithreading support is enabled.
|
||
|
@strong{Win32:} The @code{CHF_ABORT} flag is not fully supported; when
|
||
|
this flag is set the Chf library invokes @code{exit(EXIT_FAILURE)} instead
|
||
|
of @code{abort()} (not supported by Win32) to abort the application.
|
||
|
@item
|
||
|
using either @code{exit(exit_code)} or @code{pthread_exit(exit_code)}
|
||
|
if the above mentioned flag is clear. The former function is used when
|
||
|
multithreading support is not enabled, the latter when it is. The
|
||
|
argument @code{exit_code} is the value of the @code{exit_code} argument
|
||
|
given to the Chf initialization function.
|
||
|
@end itemize
|
||
|
|
||
|
The following abort messages are currently defined:
|
||
|
|
||
|
@table @code
|
||
|
@item "Not initialized"
|
||
|
The Chf library has not been correctly initialized.
|
||
|
@item "Temporary message buffer overflow"
|
||
|
The temporary message buffer used by Chf to combine the additional condition
|
||
|
arguments with the message template was overflowed. Shorten the message.
|
||
|
@item "Invalid action from last chance handler"
|
||
|
The condition handler registered first, that usually is the default
|
||
|
condition handler, has returned an invalid action code.
|
||
|
@item "Already initialized"
|
||
|
One of the Chf initialization functions was called when Chf was already
|
||
|
initialized.
|
||
|
@item "Unwind request while unwinding"
|
||
|
A condition handler has requested an unwind action when Chf was already
|
||
|
unwinding. This is not allowed.
|
||
|
@item "Improperly handled condition"
|
||
|
No condition handlers were able to properly handle the current condition
|
||
|
group. This should not occur if the default condition handler is active
|
||
|
as the last chance handler.
|
||
|
@item "Fatal condition while unwinding"
|
||
|
A fatal condition was signaled while Chf was unwinding. This is not
|
||
|
allowed because is would require another unwind to be recovered.
|
||
|
@item "Condition stack overflow"
|
||
|
An attempt was made to generate a condition while the Chf condition
|
||
|
CHF_F_COND_STACK_FULL (condition stack full) was being signaled.
|
||
|
@item "Can't prime a new Chf context"
|
||
|
Chf was unable to clone the master Chf context when a thread
|
||
|
first attempted to access its context. This message is generated
|
||
|
only when multithreading support is enabled.
|
||
|
@item "Pthread interaction failed"
|
||
|
An unrecoverable error occurred when Chf invoked a @code{pthread}
|
||
|
function. This message is generated only when multithreading support
|
||
|
is enabled.
|
||
|
@end table
|
||
|
|
||
|
No message is printed if the @code{abort_code} is @code{CHF_ABORT_SILENT};
|
||
|
this code is used, for example, by the default condition handler to terminate
|
||
|
the application when a @code{CHF_FATAL} condition occurs.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
This function is called by other Chf library functions only when they
|
||
|
detect an unrecoverable failure. Even if it has a public prototype, the user
|
||
|
should never invoke this function.
|
||
|
@item
|
||
|
@strong{Win32:} Since the standard error stream is not available, this
|
||
|
function is able to display the abort message only if it is able to
|
||
|
obtain a valid main window handle, that is, if the
|
||
|
@code{GetActiveWindow()} function yields a valid value when invoked.
|
||
|
@end itemize
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@node Library header, , ChfAbort(), Initialization and exit
|
||
|
@section Library header
|
||
|
@cindex Library header
|
||
|
|
||
|
The library header @code{Chf.h} must be included by all source modules using
|
||
|
the Chf library. Prior to include it, the following macro definitions must
|
||
|
be made:
|
||
|
|
||
|
@table @code
|
||
|
@item CHF_MODULE_ID
|
||
|
This macro must expand into an integer representing the module identifier
|
||
|
of the module the source file belongs. The module identifiers with value
|
||
|
less than 10 are reserved for Chf internal use.
|
||
|
@xref{Reserved module identifiers}.
|
||
|
|
||
|
All conditions generated by the source module will use this module
|
||
|
identifier. Even if this macro could in principle be redefined through the
|
||
|
source, it is generally inconvenient to have functions belonging to different
|
||
|
application's modules in the same source file, so it is discouraged.
|
||
|
This definition is mandatory.
|
||
|
|
||
|
@item CHF_EXTENDED_INFO
|
||
|
If this macro is set, all conditions generated by the source module
|
||
|
will include the file name and the line number as additional information
|
||
|
items. This can be useful for debugging purposes. This definition is
|
||
|
optional.
|
||
|
@end table
|
||
|
|
||
|
@strong{Win32:} The @code{tchar.h} system header must be included
|
||
|
before including @code{Chf.h}.
|
||
|
|
||
|
@node Condition generation and signal, General condition handling, Initialization and exit, Top
|
||
|
@chapter Condition generation and signal
|
||
|
@cindex Condition generation and signal
|
||
|
|
||
|
@menu
|
||
|
* Generating a condition::
|
||
|
* Signaling a condition::
|
||
|
@end menu
|
||
|
|
||
|
@node Generating a condition, Signaling a condition, Condition generation and signal, Condition generation and signal
|
||
|
@section Generating a condition
|
||
|
@cindex Generating a condition
|
||
|
|
||
|
When an unusual or noteworthy condition occurs, the application may generate
|
||
|
a condition that describes it.
|
||
|
|
||
|
@menu
|
||
|
* ChfCondition::
|
||
|
* ChfEnd::
|
||
|
* ChfSeverity::
|
||
|
* ChfErrnoCondition::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfCondition, ChfEnd, Generating a condition, Generating a condition
|
||
|
@subsection ChfCondition
|
||
|
@deftypefn Macro {} ChfCondition {...}
|
||
|
|
||
|
This macro starts the definition of a condition using the current
|
||
|
application's module specifier @code{CHF_MODULE_ID}; it must be followed by
|
||
|
these additional, mandatory, arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item int condition_code
|
||
|
This argument is the condition code; it uniquely identifies a condition
|
||
|
within the scope of the current application's module.
|
||
|
|
||
|
@item ChfSeverity severity
|
||
|
This value represents the severity of the condition. @xref{ChfSeverity}.
|
||
|
@end table
|
||
|
|
||
|
Moreover, zero or more additional argument can follow; they will be
|
||
|
immediately combined with the message template corresponding to the
|
||
|
pair (@code{CHF_MODULE_ID}, @code{condition_code}) using @code{sprintf()}.
|
||
|
All format specifiers of the latter function are allowed in the message
|
||
|
template.
|
||
|
|
||
|
As stated before, the message template is retrieved using the message
|
||
|
retrieval subsystem (@pxref{Message retrieval}) using the current Chf
|
||
|
module identifier @code{CHF_MODULE_ID} as the message set, and the
|
||
|
condition code @code{condition_code} as the message number.
|
||
|
|
||
|
If in the condition stack there isn't any condition yet, a new condition group
|
||
|
is created, otherwise the new condition is linked on top of the current
|
||
|
condition group. The condition stack supports multiple nested condition
|
||
|
groups for use in condition handlers: any condition generated inside a
|
||
|
condition handler starts a new condition group that can be individually
|
||
|
handled and signaled.
|
||
|
|
||
|
This function calls the Chf function @code{ChfAbort()} if one of the following
|
||
|
unrecoverable error condition occurs:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Chf has not been initialized correctly (abort code @code{CHF_ABORT_INIT})
|
||
|
|
||
|
@item
|
||
|
there is an overflow in the internal buffer used during the
|
||
|
generation of the partial message associated with the condition
|
||
|
(abort code @code{CHF_ABORT_MSG_OVF})
|
||
|
|
||
|
@item
|
||
|
there was an attempt to generate a condition while the Chf condition
|
||
|
@code{CHF_F_COND_STACK_FULL} (condition stack full) was being signaled
|
||
|
(abort code @code{CHF_ABORT_COND_STACK_OVF})
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node ChfEnd, ChfSeverity, ChfCondition, Generating a condition
|
||
|
@subsection ChfEnd
|
||
|
@deftypefn Macro {} ChfEnd
|
||
|
|
||
|
This macro terminates the generation of the condition, started
|
||
|
with @code{ChfCondition}; it must be followed by @code{;}. For example:
|
||
|
|
||
|
@example
|
||
|
ChfCondition
|
||
|
<condition_code>, <severity>, <additional_info>
|
||
|
ChfEnd;
|
||
|
@end example
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@c 2.1, cibrario, 26-May-2000
|
||
|
@c Expanded description of severity codes
|
||
|
@node ChfSeverity, ChfErrnoCondition, ChfEnd, Generating a condition
|
||
|
@subsection ChfSeverity
|
||
|
@deftp {Data type} ChfSeverity
|
||
|
The severity code of a condition is an enumerated type, and can assume one
|
||
|
of the following values:
|
||
|
|
||
|
@table @code
|
||
|
@item CHF_SUCCESS
|
||
|
This condition represents the successful completion of an application's
|
||
|
action; when generated in an application's module it is usually signaled
|
||
|
immediately after generation, it is not reported to the module caller
|
||
|
and does not disrupt the normal control flow of the application.
|
||
|
|
||
|
@item CHF_INFO
|
||
|
This condition conveys an information message to the application's user,
|
||
|
but it in no way represents an error indication; when generated in an
|
||
|
application's module it is usually signaled immediately after
|
||
|
generation, it is not reported to the module caller and does not disrupt
|
||
|
the normal control flow of the application.
|
||
|
|
||
|
@item CHF_WARNING
|
||
|
This condition has been generated to warn the application's user that a
|
||
|
potentially abnormal situation occurred, but the application's module
|
||
|
was able to complete successfully the action that was requested to it,
|
||
|
perhaps incompletely. It is usually not signaled immediately after
|
||
|
generation, it is reported to the caller using some status reporting
|
||
|
mechanism, and it requires only a minimal, local disruption of the
|
||
|
control flow of the application to be recovered.
|
||
|
|
||
|
@item CHF_ERROR
|
||
|
An error occurred and the application's module was not able to complete its
|
||
|
work, but it still may be possible to perform a local recovery and resume the
|
||
|
normal application's control flow. It is usually not signaled immediately
|
||
|
after generation and it is reported to the caller using some status
|
||
|
reporting mechanism.
|
||
|
|
||
|
@item CHF_FATAL
|
||
|
A fatal error occurred, and a global recovery action is required, because
|
||
|
the normal application's control flow can't be safely resumed. The Chf library
|
||
|
enforces that, when @code{ChfSignal()} is called with a fatal condition, the
|
||
|
control will never return to the instruction following the @code{ChfSignal()}
|
||
|
call. It is usually signaled immediately after generation.
|
||
|
|
||
|
@end table
|
||
|
@end deftp
|
||
|
|
||
|
@node ChfErrnoCondition, , ChfSeverity, Generating a condition
|
||
|
@subsection ChfErrnoCondition
|
||
|
@deftypefn Macro {} ChfErrnoCondition
|
||
|
|
||
|
This macro generates a condition from the current value of the @code{errno}
|
||
|
variable. The module identifier of the condition is set to the special
|
||
|
value @code{CHF_ERRNO_SET}. The severity is always @code{CHF_ERROR}.
|
||
|
|
||
|
@strong{Win32:} This macro is not supported and has no effect when invoked.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node Signaling a condition, , Generating a condition, Condition generation and signal
|
||
|
@section Signaling a condition
|
||
|
@cindex Signaling a condition
|
||
|
|
||
|
A condition already generated with one of the macros discussed in the
|
||
|
previous section can be signaled using the following function, that starts
|
||
|
the condition signaling sequence.
|
||
|
|
||
|
@menu
|
||
|
* ChfSignal()::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfSignal(), , Signaling a condition, Signaling a condition
|
||
|
@subsection ChfSignal()
|
||
|
@cindex ChfSignal()
|
||
|
@deftypefn Function void ChfSignal (void)
|
||
|
@end deftypefn
|
||
|
|
||
|
This function signals the current condition group. If the final action
|
||
|
requested by the condition handlers invoked during the signaling operation
|
||
|
was @code{CHF_CONTINUE} and the overall severity of the condition group
|
||
|
was lower than @code{CHF_FATAL}, this function will return to the caller,
|
||
|
otherwise either a non-local control transfer will occur (@code{CHF_UNWIND})
|
||
|
or the invoking application/thread will be terminated.
|
||
|
|
||
|
During the signaling of a condition group the following actions are
|
||
|
accomplished:
|
||
|
|
||
|
@table @bullet
|
||
|
@item
|
||
|
First of all, a check is made to ensure that the Chf subsystem has been
|
||
|
correctly initialized. If not, the function @code{ChfAbort} is called.
|
||
|
@item
|
||
|
The state of Chf is changed to @code{CHF_SIGNALING} if it was @code{CHF_IDLE},
|
||
|
and to @code{CHF_SIGNAL_UNWINDING} if it was @code{CHF_UNWINDING}.
|
||
|
@item
|
||
|
If there is not any active condition group, the function does nothing more,
|
||
|
restores the saved Chf state and returns to the caller.
|
||
|
@item
|
||
|
If there is an active condition group, the currently active condition handlers
|
||
|
are invoked, starting from the one registered last.
|
||
|
@item
|
||
|
Each condition handler can recursively invoke @code{ChfGenerate()} and
|
||
|
@code{ChfSignal()}. @code{ChfGenerate()}, when invoked, will create a new
|
||
|
condition group, and @code{ChfSignal()} will signal the condition group
|
||
|
just created.
|
||
|
@item
|
||
|
When the Chf state is @code{CHF_SIGNALING}, any new condition group generated
|
||
|
but not yet signaled when the current handler exits is merged
|
||
|
with the condition group currently being signaled, in order to allow
|
||
|
the condition handlers to add their own conditions to the condition
|
||
|
group. If the severity of the previous condition group was @code{CHF_FATAL},
|
||
|
the severity of the new group is forced to @code{CHF_FATAL}, too.
|
||
|
When the Chf state is @code{CHF_UNWINDING}, the condition group for
|
||
|
which the unwind has been requested is 'frozen', no further
|
||
|
modifications are allowed on it, and the new condition group is simply
|
||
|
discarded.
|
||
|
@item
|
||
|
The condition handlers calling sequence terminates when either the handler
|
||
|
stack is exhausted (all condition handlers have been called) or when an
|
||
|
handler requests either the action @code{CHF_CONTINUE},
|
||
|
@code{CHF_UNWIND} or @code{CHF_UNWIND_KEEP}.
|
||
|
Please note that the @code{CHF_CONTINUE} action cannot be requested if
|
||
|
the severity of the condition group is @code{CHF_FATAL}; when this occurs,
|
||
|
the action is automatically changed to @code{CHF_RESIGNAL} instead.
|
||
|
@item
|
||
|
If the action @code{CHF_CONTINUE} has been requested and it is allowed, Chf
|
||
|
discards the current condition group, restored the saved Chf state and
|
||
|
returns to the instruction following the call to @code{ChfSignal()}, that
|
||
|
started the signaling activities.
|
||
|
@item
|
||
|
If either one of the actions @code{CHF_UNWIND} or @code{CHF_UNWIND_KEEP}
|
||
|
has been requested and it is allowed, that is,
|
||
|
no other unwinds are already in progress, the current Chf state is set
|
||
|
to @code{CHF_UNWINDING} and all handlers that were registered
|
||
|
after the handler that requested the unwind are called again, starting
|
||
|
from the one registered last, so that they can perform any final cleanup
|
||
|
operation they require for proper operation. The handler that requested
|
||
|
the unwind is called again, too, in the same fashion. Immediately after
|
||
|
this, the unwinded condition handlers are removed from the handler stack
|
||
|
and discarded, the current condition group and any other group generated
|
||
|
after it are destroyed, the Chf state is changed back to @code{CHF_IDLE}
|
||
|
and a non-local control transfer is executed through a
|
||
|
@code{siglongjmp()}, using the @code{unwind_context} associated with the
|
||
|
handler that requested the unwind as target. The @code{ChfSignal()}
|
||
|
invocation that started the signaling activities will never return to
|
||
|
the caller. If the requested action is @code{CHF_UNWIND_KEEP} everything
|
||
|
goes as described above, except that the current condition group and
|
||
|
any other group generated after it are @strong{not} destroyed, so they can
|
||
|
still be accessed after the non-local control transfer has taken place.
|
||
|
@item
|
||
|
If no handlers were able to handle the condition, the invoking
|
||
|
application/thread is terminated with @code{ChfAbort()}.
|
||
|
@item
|
||
|
If an handler returned an invalid action code and it is not the condition
|
||
|
handler that was registered first, a new condition group is generated and
|
||
|
immediately signaled, containing the condition @code{CHF_F_INVALID_ACTION}
|
||
|
with module identifier @code{CHF_SET}.
|
||
|
@end table
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c Renamed 'condition handling' -> 'general condition handling'
|
||
|
@node General condition handling, Structured condition handling, Condition generation and signal, Top
|
||
|
@chapter Condition handling
|
||
|
@cindex Condition handling
|
||
|
|
||
|
@menu
|
||
|
* Condition handlers::
|
||
|
* Condition descriptors::
|
||
|
* Condition handling state::
|
||
|
* Handler actions::
|
||
|
* Default handler::
|
||
|
@end menu
|
||
|
|
||
|
@node Condition handlers, Condition descriptors, General condition handling, General condition handling
|
||
|
@section Condition handlers
|
||
|
@cindex Condition handlers
|
||
|
|
||
|
The Chf library maintains a LIFO stack of active condition handlers. Each
|
||
|
condition handler is a function which has type @code{ChfHandler}.
|
||
|
Moreover, the functions described below are available to push and pop
|
||
|
a condition handler to/from the condition handler stack.
|
||
|
|
||
|
@menu
|
||
|
* ChfHandler::
|
||
|
* ChfPushHandler()::
|
||
|
* ChfPopHandler()::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfHandler, ChfPushHandler(), Condition handlers, Condition handlers
|
||
|
@subsection ChfHandler
|
||
|
@cindex ChfHandler
|
||
|
@deftp {Data Type} ChfHandler
|
||
|
|
||
|
The condition handler data type is defined as follows:
|
||
|
|
||
|
@example
|
||
|
typedef /* Condition handler */
|
||
|
ChfAction (*ChfHandler)(
|
||
|
const ChfDescriptor *,
|
||
|
const ChfState,
|
||
|
ChfPointer
|
||
|
);
|
||
|
@end example
|
||
|
|
||
|
The condition handler receives the following arguments when invoked:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item const ChfDescriptor *
|
||
|
is a pointer to the condition group that is being signaled.
|
||
|
|
||
|
@item const ChfState
|
||
|
represents the current state of the condition handling facility.
|
||
|
|
||
|
@item ChfPointer
|
||
|
is a copy of the @code{handler_context} pointer passed to the
|
||
|
@code{ChfPushHandler()} invocation that established the condition
|
||
|
handler.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
The handler must return an action code, represented by a value
|
||
|
of type @code{ChfAction}.
|
||
|
|
||
|
Before returning, the condition handler can generate other conditions,
|
||
|
without signaling them, with the purpose of better specify the current
|
||
|
condition group; these conditions will be added on top of the current
|
||
|
group when the handler returns. The next handler, if any, will be invoked
|
||
|
on the updated condition group.
|
||
|
|
||
|
The severity @code{CHF_FATAL} is 'sticky', that is, any new condition
|
||
|
linked to a condition group where the topmost condition has that
|
||
|
severity will be forced to the same severity level.
|
||
|
|
||
|
If the condition handler itself generates and signals a new condition
|
||
|
group, its superior condition handlers will be invoked on the new
|
||
|
condition group only. When the new signaling sequence is completed,
|
||
|
the old sequence will be resumed if appropriate, i.e. if a superior
|
||
|
handler has requested the @code{CHF_CONTINUE} action and the severity
|
||
|
of the new condition group allows it to do so.
|
||
|
|
||
|
@end deftp
|
||
|
|
||
|
|
||
|
@node ChfPushHandler(), ChfPopHandler(), ChfHandler, Condition handlers
|
||
|
@subsection ChfPushHandler()
|
||
|
@cindex Condition handlers
|
||
|
@cindex Adding condition handlers
|
||
|
@deftypefn Function void ChfPushHandler (ChfHandler new_handler, void *unwind_context, ChfPointer handler_context)
|
||
|
|
||
|
This function pushes the new condition handler @code{new_handler} with
|
||
|
its associated @code{siglongjmp()} context, pointed by
|
||
|
@code{unwind_context}, into the handler stack. If @code{new_handler} is
|
||
|
@code{CHF_NULL_HANDLER}, the special builtin structured condition
|
||
|
handling helper is pushed; see @ref{Structured condition handling}, for
|
||
|
further information.
|
||
|
|
||
|
Moreover, this function saves a copy of the opaque pointer
|
||
|
@code{handler_context}; it will be passed to @code{new_handler} upon each
|
||
|
subsequent activation, and therefore can be used as a private handler context
|
||
|
pointer. The user must ensure that the information pointed by
|
||
|
@code{handler_context}, if any, will remain valid until @code{new_handler}
|
||
|
is popped from the condition stack.
|
||
|
|
||
|
The pointer @code{handler_context} may be set to the special (null) value
|
||
|
@code{CHF_NULL_POINTER} to indicate that the handler hasn't any private
|
||
|
context information.
|
||
|
|
||
|
If, in the future, the handler will request the @code{CHF_UNWIND}
|
||
|
action, the @code{sigsetjmp()} function invocation that established
|
||
|
@code{unwind_context} will appear to return again.
|
||
|
|
||
|
The pointer @code{unwind_context} can be the reserved (null) pointer
|
||
|
@code{CHF_NULL_CONTEXT}; in this case, if the handler will request the
|
||
|
@code{CHF_UNWIND} action, the invoking application/thread will be
|
||
|
silently terminated calling @code{ChfAbort()} with abort code
|
||
|
@code{CHF_ABORT_SILENT}.
|
||
|
|
||
|
If an error occurs during the execution, the function generates
|
||
|
and immediately signals one of the conditions listed below; the function
|
||
|
will never return directly to the caller, since all conditions have
|
||
|
severity @code{CHF_FATAL}.
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_F_BAD_STATE
|
||
|
Bad Chf state for requested operation. A new handler can be added to the
|
||
|
handler stack only if the condition handling subsystem is idle.
|
||
|
|
||
|
@item CHF_F_HDLR_STACK_FULL,
|
||
|
The handler stack is full and the new handler can't be added.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
if Chf hasn't been initialized.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfPopHandler(), , ChfPushHandler(), Condition handlers
|
||
|
@subsection ChfPopHandler()
|
||
|
@cindex Condition handlers
|
||
|
@cindex Removing condition handlers
|
||
|
@deftypefn Function void ChfPopHandler (void)
|
||
|
|
||
|
This function pops the topmost condition handler from the handler stack and
|
||
|
returns to the caller.
|
||
|
|
||
|
If an error occurs during the execution, the function generates
|
||
|
and immediately signals one of the conditions listed below; the function
|
||
|
will never return directly to the caller, since all conditions have
|
||
|
severity @code{CHF_FATAL}.
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_F_BAD_STATE
|
||
|
Bad Chf state for requested operation. Handlers can be removed from the
|
||
|
handler stack only if the condition handling subsystem is idle.
|
||
|
|
||
|
@item CHF_F_HDLR_STACK_EMPTY
|
||
|
The handler stack is empty.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
if Chf hasn't been initialized.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node Condition descriptors, Condition handling state, Condition handlers, General condition handling
|
||
|
@section Condition descriptors
|
||
|
@cindex Condition descriptors
|
||
|
@deftp {Data Type} ChfDescriptor
|
||
|
|
||
|
The condition descriptor contains all information Chf has about a
|
||
|
condition code. Its fields must not be accessed directly, but using
|
||
|
the macros the Chf library provides for this purpose.
|
||
|
|
||
|
@end deftp
|
||
|
|
||
|
The following macros are provided to access a condition descriptor:
|
||
|
|
||
|
@deftypefn Macro {ChfDescriptor *} ChfGetNextDescriptor (Chf Descriptor *d)
|
||
|
@cindex Next condition descriptor
|
||
|
|
||
|
Returns to the caller the condition descriptor that hierarchically
|
||
|
follows @code{d} in the current condition group, or the special
|
||
|
value @code{CHF_NULL_DESCRIPTOR} if @code{d} is the last descriptor of the
|
||
|
group.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro int ChfGetModuleId (Chf Descriptor *d)
|
||
|
@cindex Module identifier
|
||
|
|
||
|
Returns to the caller the identifier of the module that generated
|
||
|
the condition @code{d}.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro int ChfGetConditionCode (Chf Descriptor *d)
|
||
|
@cindex Condition Code
|
||
|
|
||
|
Returns to the caller the condition code of the condition @code{d}.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro ChfSeverity ChfGetSeverity (Chf Descriptor *d)
|
||
|
@cindex Severity
|
||
|
|
||
|
Returns to the caller the severity level of the condition @code{d}.
|
||
|
@xref{ChfSeverity}.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro int ChfGetLineNumber (Chf Descriptor *d)
|
||
|
@cindex Line number
|
||
|
|
||
|
Returns to the caller the source line number where the condition @code{d}
|
||
|
was generated. This piece of information is available only if the
|
||
|
Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source
|
||
|
file that generated the condition was compiled, otherwise the special
|
||
|
value @code{CHF_UNKNOWN_LINE_NUMBER} is returned instead.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {const char *} ChfGetFileName (Chf Descriptor *d)
|
||
|
@cindex File name
|
||
|
|
||
|
Returns to the caller the file name where the condition @code{d}
|
||
|
was generated. This piece of information is available only if the
|
||
|
Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source
|
||
|
file that generated the condition was compiled, otherwise the special
|
||
|
value @code{CHF_UNKNOWN_FILE_NAME} is returned instead.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {char *} ChfGetPartialMessage (Chf Descriptor *d)
|
||
|
@cindex Partial condition message
|
||
|
|
||
|
Returns to the caller the partial condition message that was associated
|
||
|
with the condition @code{d} when it was generated. The partial condition
|
||
|
message contains the result of the execution of @code{sprintf()} using
|
||
|
the message template associated with the condition as format, and the
|
||
|
ancillary condition arguments as additional arguments.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
|
||
|
@node Condition handling state, Handler actions, Condition descriptors, General condition handling
|
||
|
@section Condition handling state
|
||
|
@cindex Condition handling state
|
||
|
@deftp {Data Type} ChfState
|
||
|
This enumerated type describes the current state of the Condition Handling
|
||
|
Facility. It can have one of the following values:
|
||
|
|
||
|
@table @code
|
||
|
@item CHF_UNKNOWN
|
||
|
The Chf library has not been initialized, or the initialization has failed.
|
||
|
Normally, the user never sees this value, because the main use of
|
||
|
@code{ChfState} values is inside condition handlers, and they are never
|
||
|
invoked when the Chf library has not been initialized correctly.
|
||
|
|
||
|
@item CHF_IDLE
|
||
|
This is the normal state of the condition handling facility. In this state,
|
||
|
the condition stack contains zero or more condition descriptors corresponding
|
||
|
to conditions that have been generated but have not been signaled yet.
|
||
|
The application follows its normal control flow.
|
||
|
|
||
|
@item CHF_SIGNALING
|
||
|
The Condition Handling Facility is invoking the hierarchy of active
|
||
|
condition handlers because @code{ChfSignal()} has been invoked with a
|
||
|
non-empty condition stack. None of the condition handlers invoked so far
|
||
|
has requested an unwind operation.
|
||
|
|
||
|
@item CHF_UNWINDING
|
||
|
The Condition Handling Facility is unwinding one or more condition handlers,
|
||
|
because another, superior, handler has requested an unwind operation.
|
||
|
All handlers being unwinded are called once with Chf in this state to allow
|
||
|
them to perform any final cleanup operation, and immediately after that
|
||
|
they are removed from the condition stack. During unwind,
|
||
|
the action code returned by the handler being unwinded is ignored.
|
||
|
|
||
|
@item CHF_SIGNAL_UNWINDING
|
||
|
While Chf was performing an unwind operation, one of the handlers being
|
||
|
unwinded has signaled another condition group. The superiors of the
|
||
|
signaling handler are invoked with Chf in this state, then the unwind
|
||
|
operation is resumed.
|
||
|
|
||
|
@end table
|
||
|
@end deftp
|
||
|
|
||
|
@node Handler actions, Default handler, Condition handling state, General condition handling
|
||
|
@section Handler actions
|
||
|
@cindex Handler actions
|
||
|
@deftp {Data Type} ChfAction
|
||
|
|
||
|
Enumerated type representing the set of mutually exclusive actions that a
|
||
|
condition handler can request to the condition handling facility. It can
|
||
|
have the following values:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CHF_CONTINUE
|
||
|
Resume the application from the instruction immediately following the
|
||
|
@code{ChfSignal()} call that triggered the invocation of the condition handler.
|
||
|
This action is not allowed if the severity of the current condition is
|
||
|
@code{CHF_FATAL}, since this severity always requires global recovery
|
||
|
to take place. In this case the @code{CHF_CONTINUE} is automatically
|
||
|
changed to @code{CHF_RESIGNAL} when encountered.
|
||
|
|
||
|
@item CHF_RESIGNAL
|
||
|
Invoke the next handler in the handler stack with the same condition.
|
||
|
This action must be used when the current condition handler was not able
|
||
|
to recover the condition.
|
||
|
|
||
|
@item CHF_UNWIND
|
||
|
Unwind the application's stack and restore the @code{unwind_context}
|
||
|
associated with the condition handler, performing a non-local control
|
||
|
transfer. @xref{ChfPushHandler()}.
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c Added descruption of CHF_UNWIND_KEEP
|
||
|
@item CHF_UNWIND_KEEP
|
||
|
Unwind the application's stack and restore the @code{unwind_context}
|
||
|
associated with the condition handler, performing a non-local control
|
||
|
transfer. Unlike @code{CHF_UNWIND}, the current condition group
|
||
|
at the time of the unwind is @strong{not} destroyed,
|
||
|
and can still be accessed after the non-local control transfer has
|
||
|
taken place.
|
||
|
@end table
|
||
|
@end deftp
|
||
|
|
||
|
@node Default handler, , Handler actions, General condition handling
|
||
|
@section Default handler
|
||
|
@cindex Default handler
|
||
|
|
||
|
The default condition handler of Chf is automatically
|
||
|
pushed into the condition handler stack by the Chf initialization
|
||
|
functions. It performs the following functions:
|
||
|
|
||
|
@table @bullet
|
||
|
@item
|
||
|
if called during an unwind, it returns immediately to the caller,
|
||
|
requesting the action @code{CHF_RESIGNAL}, else
|
||
|
|
||
|
@item
|
||
|
if the severity of the condition being signaled is greater than
|
||
|
@code{CHF_SUCCESS}, it prints the messages associated with the entire
|
||
|
condition group on stderr using the standard function
|
||
|
@code{ChfBuildMessage()} to build the messages.
|
||
|
@strong{Win32: } Since the standard error stream is not available,
|
||
|
the default handler does not print anything out.
|
||
|
|
||
|
@item
|
||
|
if the severity of the condition being signaled is less than
|
||
|
@code{CHF_FATAL}, it returns to the caller requesting the action
|
||
|
@code{CHF_CONTINUE}, else
|
||
|
|
||
|
@item
|
||
|
if the @code{CHF_FATAL} condition was @strong{not} signaled during an unwind
|
||
|
operation, it returns to the caller requesting the action
|
||
|
@code{CHF_UNWIND}, otherwise it requests the action @code{CHF_RESIGNAL}.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c New chapter: Structured condition handling
|
||
|
@node Structured condition handling, Chf conditions, General condition handling, Top
|
||
|
@chapter Structured condition handling
|
||
|
@cindex Structured condition handling
|
||
|
|
||
|
Structured condition handling places the condition handler associated
|
||
|
with a block of code next to the block itself, instead of into a separate
|
||
|
procedure. Even if it is less flexible and powerful with respect to the
|
||
|
general handling method described before, it is often clearer and
|
||
|
simpler to implement. Chf supports both styles of condition handling;
|
||
|
the structured condition handling is layered above the general one.
|
||
|
|
||
|
@menu
|
||
|
* Syntax of structured condition handlers::
|
||
|
* Chf behavior during structured condition handling::
|
||
|
@end menu
|
||
|
|
||
|
@node Syntax of structured condition handlers, Chf behavior during structured condition handling, Structured condition handling, Structured condition handling
|
||
|
@section Syntax of structured condition handlers
|
||
|
@cindex Syntax of structured condition handlers
|
||
|
|
||
|
The syntax establishing a structured condition handler is as follows:
|
||
|
|
||
|
@example
|
||
|
ChfTry
|
||
|
@{
|
||
|
... body ...
|
||
|
@}
|
||
|
ChfCatch
|
||
|
@{
|
||
|
const ChfDescriptor *exc = ChfGetTopCondition();
|
||
|
... condition handler ...
|
||
|
@}
|
||
|
ChfEndTry;
|
||
|
@end example
|
||
|
|
||
|
The macros @code{ChfTry}, @code{ChfCatch} and @code{ChfEndTry}
|
||
|
expand as follows:
|
||
|
|
||
|
@example
|
||
|
<<
|
||
|
@{
|
||
|
sigjmp_buf _chf_sigjmp_buf;
|
||
|
if(sigsetjmp(_chf_sigjmp_buf, 1) == 0)
|
||
|
@{
|
||
|
ChfPushHandler(CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER);
|
||
|
>>
|
||
|
@{
|
||
|
... body ...
|
||
|
@}
|
||
|
<<
|
||
|
ChfPopHandler();
|
||
|
@}
|
||
|
else
|
||
|
@{
|
||
|
>>
|
||
|
@{
|
||
|
const ChfDescriptor *exc = ChfGetTopCondition();
|
||
|
... condition handler ...
|
||
|
@}
|
||
|
<<
|
||
|
ChfDiscard();
|
||
|
@}
|
||
|
@}
|
||
|
>>
|
||
|
@end example
|
||
|
|
||
|
Above, @code{<<} and @code{>>} mark the starting and ending point of
|
||
|
each macro expansion, respectively.
|
||
|
|
||
|
The @code{body} is either a statement or a block of statements (a block
|
||
|
is shown in the example) to be protected. If an exception with severity
|
||
|
equal to @code{CHF_FATAL} is signaled during the execution of
|
||
|
@code{body}, control is transferred to the @code{condition handler}
|
||
|
following @code{ChfCatch}.
|
||
|
|
||
|
The handler can then retrieve the condition group associated with the
|
||
|
exception using @code{ChfGetTopCondition()}, as shown in the example,
|
||
|
and must perform one of the following actions:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Handle the exception; when the condition handler completes, that is, its
|
||
|
last statement has been executed, the current condition group is
|
||
|
automatically discarded and control is transferred to the code that
|
||
|
follows @code{ChfEndTry}.
|
||
|
@item
|
||
|
Resignal the exception, possibly after adding one or more conditions to
|
||
|
it; in this case, the handler explicitly calls @code{ChfSignal()}.
|
||
|
In response, Chf continues to search for a handler that actually
|
||
|
handles the exception, in the @code{ChfTry}/@code{ChfCatch} blocks
|
||
|
enclosing the current one, in inner to outer order. The control
|
||
|
will never be returned to the resignaling handler.
|
||
|
@end itemize
|
||
|
|
||
|
Notice that it is not possible for the condition handler to resume
|
||
|
the thread of execution disrupted by the exception. Resuming is
|
||
|
possible only when the signaled condition has severity less than
|
||
|
@code{CHF_FATAL}: in this case the @code{condition handler} is
|
||
|
not invoked, the usual condition signaling sequence takes place
|
||
|
and the @code{CHF_CONTINUE} action requested by any general
|
||
|
condition handler is honored.
|
||
|
|
||
|
Thus, structured condition handling is further simplified because:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Conditions with severity less than @code{CHF_WARNING} are usually
|
||
|
automatically signaled immediately after generation and are not reported
|
||
|
to the caller; they are informational conditions only, and they must not
|
||
|
disrupt the normal control flow of the application. Accordingly, the
|
||
|
structured condition handler is @strong{not} invoked when a
|
||
|
success/informational condition is signaled in its @code{ChfTry} body.
|
||
|
@item
|
||
|
@code{CHF_WARNING} conditions generated by a module are usually not
|
||
|
signaled immediately after generation, but are reported to the
|
||
|
caller using some status reporting mechanism. When a warning
|
||
|
condition is generated by a module, it indicates that its execution
|
||
|
has been at least partially successful; this usually means that
|
||
|
the disruption of the control flow of the application can be kept to
|
||
|
a minimum and handled locally. Accordingly, the structured condition
|
||
|
handler is @strong{not} invoked when a warning condition
|
||
|
is signaled in its @code{ChfTry} body.
|
||
|
@item
|
||
|
@code{CHF_ERROR} conditions generated by a module indicate that the
|
||
|
module execution has been unsuccessful; they are usually reported to the
|
||
|
caller using some status reporting mechanisms. An error condition
|
||
|
indicates that a significant disruption of the control flow of the
|
||
|
application is required to recover, and that local handling is still
|
||
|
possible but could not suffice. Accordingly, the structured condition
|
||
|
handler is @strong{not} invoked when an error condition is signaled in
|
||
|
its @code{ChfTry} body. Notice also that if the @code{ChfTry} body is
|
||
|
not able to locally recover the condition, it can add a @code{CHF_FATAL}
|
||
|
condition to the condition group and signal the modified group, thus
|
||
|
triggering the invocation of the structured condition handler.
|
||
|
@item
|
||
|
@code{CHF_FATAL} conditions are usually signaled immediately after
|
||
|
generation and always require a global recovery action.
|
||
|
Accordingly, the structured condition handler is
|
||
|
invoked when a warning condition is signaled in its @code{ChfTry} body.
|
||
|
@end itemize
|
||
|
|
||
|
Notice also that control is transferred to the structured exception
|
||
|
handler by means of a @code{siglongjmp()} sequence. Therefore,
|
||
|
if the structured exception handler needs to access automatic
|
||
|
variables, they should be declared @code{volatile}.
|
||
|
|
||
|
If no handlers are able to handle an exception, the default Chf
|
||
|
condition handler is invoked last. @xref{Default handler}, for a more
|
||
|
detailed description of its operation.
|
||
|
|
||
|
If no exceptions are raised during the execution of @code{body},
|
||
|
the @code{condition handler} is skipped and execution continues
|
||
|
immediately after @code{ChfEndTry}.
|
||
|
|
||
|
@node Chf behavior during structured condition handling, , Syntax of structured condition handlers, Structured condition handling
|
||
|
@section Chf behavior during structured condition handling
|
||
|
@cindex Chf behavior during structured condition handling
|
||
|
|
||
|
When a condition is signaled and the special structured condition
|
||
|
handling helper is invoked, the following sequence of events occurs:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Chf transitions to state @code{CHF_SIGNALING} and starts
|
||
|
the handler calling sequence.
|
||
|
@item
|
||
|
If any handler invoked before the structured condition handling helper
|
||
|
requests either the @code{CHF_CONTINUE} or the @code{CHF_UNWIND}
|
||
|
action, that action is executed as usual.
|
||
|
@item
|
||
|
When invoked, the structured condition handling helper immediately
|
||
|
requests the action @code{CHF_UNWIND_KEEP}.
|
||
|
@item
|
||
|
Chf transitions to state @code{CHF_UNWINDING} and invokes all handlers
|
||
|
registered after the structured condition handling helper again. Such
|
||
|
handlers can then perform whatever final cleanup operations they need.
|
||
|
@item
|
||
|
Chf invokes the structured condition handling helper again; the helper
|
||
|
immediately returns without doing anything, since Chf is now in state
|
||
|
@code{CHF_UNWINDING}.
|
||
|
@item
|
||
|
Chf transitions to the @code{CHF_IDLE} state and performs a non-local
|
||
|
control transfer to the structured condition handler's unwind context;
|
||
|
this corresponds to the code that follows @code{ChfCatch}.
|
||
|
The current condition group is not removed from the condition stack.
|
||
|
@item
|
||
|
Since the current condition group has not been removed from the
|
||
|
condition stack, the code that follows @code{ChfCatch} can freely
|
||
|
access the condition group using @code{ChfGetTopCondition()}
|
||
|
and @code{ChfGetNextDescriptor()}.
|
||
|
@item
|
||
|
If any new condition is generated in this phase, it is merged with the
|
||
|
current condition group; the condition group can be re-signaled at will
|
||
|
by invoking @code{ChfSignal()}.
|
||
|
@item
|
||
|
Immediately after the code that follows @code{ChfCatch} completes,
|
||
|
@code{ChfDiscard()} is automatically invoked to remove the topmost
|
||
|
condition group from the stack.
|
||
|
@end itemize
|
||
|
|
||
|
If the structured condition handling helper is invoked when Chf is in
|
||
|
@code{CHF_SIGNAL_UNWINDING}, it immediately requests the
|
||
|
@code{CHF_RESIGNAL} action, because a further unwind request is neither
|
||
|
allowed nor useful in this case.
|
||
|
|
||
|
The structured condition handling helper makes no use of
|
||
|
@code{handler_context}.
|
||
|
|
||
|
In summary, the following structured condition handling macros
|
||
|
are currently available:
|
||
|
|
||
|
@menu
|
||
|
* ChfTry::
|
||
|
* ChfCatch::
|
||
|
* ChfEndTry::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfTry, ChfCatch, Chf behavior during structured condition handling, Chf behavior during structured condition handling
|
||
|
@subsection ChfTry
|
||
|
@deftypefn Macro {} ChfTry {...}
|
||
|
|
||
|
This macro introduces a new structured condition handling body.
|
||
|
The body is either a statement or a block of statements to be
|
||
|
protected: if a @code{CHF_FATAL} exception is signaled during its
|
||
|
execution, control is transferred to the condition handling code
|
||
|
following @code{ChfCatch}.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfCatch, ChfEndTry, ChfTry, Chf behavior during structured condition handling
|
||
|
@subsection ChfCatch
|
||
|
@deftypefn Macro {} ChfCatch {...}
|
||
|
|
||
|
This macro must follow @code{ChfTry} and introduces a new structured
|
||
|
condition handler following it; the handler can be either a statement or
|
||
|
a block of statements. If a @code{CHF_FATAL} exception is signaled
|
||
|
during the execution of the body protected by @code{ChfTry}, control is
|
||
|
transferred to the condition handling code following @code{ChfCatch}.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
@node ChfEndTry, , ChfCatch, Chf behavior during structured condition handling
|
||
|
@subsection ChfEndTry
|
||
|
@deftypefn Macro {} ChfEndTry
|
||
|
|
||
|
This macro marks the end of a body/condition handler pair.
|
||
|
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node Chf conditions, Message retrieval, Structured condition handling, Top
|
||
|
@chapter Chf conditions
|
||
|
@cindex Chf conditions
|
||
|
|
||
|
The Chf library can itself generate and signal the following conditions.
|
||
|
All conditions are fatal, i.e. require a global recovery action to take
|
||
|
place to be handled.
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_COND_STACK_FULL
|
||
|
The user attempted to generate a condition while the condition stack was full;
|
||
|
this condition is generated anyway using a reserved stack entry.
|
||
|
No additional conditions can be generated until the handling of this condition
|
||
|
is completed, otherwise the application will be aborted.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_HDLR_STACK_FULL
|
||
|
The function @code{ChfPushHandler()} was called while the handler stack
|
||
|
was full; the new handler is not registered and this condition is signaled
|
||
|
using the old handler hierarchy.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_HDLR_STACK_EMPTY
|
||
|
A function requiring at least one condition handler to be active
|
||
|
found an empty handler stack.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_BAD_STATE
|
||
|
The current state of Chf was not appropriate to invoke a certain
|
||
|
Chf function. The invoked function does not do anything but
|
||
|
signaling this condition.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_INVALID_ACTION
|
||
|
During the current signaling sequence an handler returned an invalid
|
||
|
action code. A new condition group, containing only this condition, is
|
||
|
generated and immediately signaled. The first handler called to handle
|
||
|
the new condition group will be the handler registered immediately before
|
||
|
the faulting one.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_MALLOC
|
||
|
Many Chf functions dynamically allocate memory. This condition is generated
|
||
|
and signaled when a dynamic memory allocation attempt failed, and the library
|
||
|
was unable to recover in another way.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_NOT_AVAILABLE
|
||
|
The function is not available on the current platform. This condition
|
||
|
is returned by some Chf initialization functions instead of being
|
||
|
signaled, because it prevents the Chf subsystem to be initialized and,
|
||
|
therefore, to function properly.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_SETLOCALE
|
||
|
The @code{setlocale()} function failed during the initialization of the
|
||
|
message catalog-based message retrieval subsystem. This condition is returned
|
||
|
by the Chf initialization function instead of being signaled, because it
|
||
|
prevents the Chf subsystem to be initialized and, therefore, to function
|
||
|
properly.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_F_CATOPEN
|
||
|
The @code{catopen()} function failed during the initialization of the
|
||
|
message catalog-based message retrieval subsystem. This condition is returned
|
||
|
by the Chf initialization function instead of being signaled, because it
|
||
|
prevents the Chf subsystem to be initialized and, therefore, to function
|
||
|
properly.
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node Message retrieval, Multithreading support, Chf conditions, Top
|
||
|
@chapter Message retrieval
|
||
|
@cindex Message retrieval
|
||
|
The message retrieval subsystem is responsible to retrieve the message
|
||
|
fragments needed by the Chf library to generate the messages associated
|
||
|
with condition codes.
|
||
|
|
||
|
Basically, given a message set identifier (that usually has the same value
|
||
|
as the module identifier for which the condition is being generated) and
|
||
|
a message number (that usually has the same value as the condition code),
|
||
|
it must retrieve and return to the caller a suitable message associated
|
||
|
to it. It the message cannot be found, it must return a default message
|
||
|
pointer Chf provides.
|
||
|
|
||
|
Some module identifiers/message sets are used for special purposes.
|
||
|
@xref{Reserved module identifiers}.
|
||
|
|
||
|
@menu
|
||
|
* Retrieving a message::
|
||
|
* Reserved module identifiers::
|
||
|
* Defining a new message retrieval subsystem::
|
||
|
@end menu
|
||
|
|
||
|
@node Retrieving a message, Reserved module identifiers, Message retrieval, Message retrieval
|
||
|
@section Retrieving a message
|
||
|
The following functions directly interact with the message retrieval subsystem:
|
||
|
|
||
|
@menu
|
||
|
* ChfGetMessage()::
|
||
|
* ChfBuildMessage()::
|
||
|
@end menu
|
||
|
|
||
|
@node ChfGetMessage(), ChfBuildMessage(), Retrieving a message, Retrieving a message
|
||
|
@subsection ChfGetMessage()
|
||
|
@deftypefn Function {const char *} ChfGetMessage (const int module_id, const int condition_code, const char *default_message)
|
||
|
|
||
|
This function transparently uses the Chf message retrieval subsystem to
|
||
|
retrieve the message associated with the pair
|
||
|
(@code{module_id}, @code{condition_code}) and returns a pointer to it.
|
||
|
The function will return @code{default_message} instead, if it was not able
|
||
|
to retrieve the message. If @code{module_id==CHF_ERRNO_SET}, the function
|
||
|
will additionally invoke @code{strerror()}, if necessary, to retrieve the
|
||
|
message.
|
||
|
|
||
|
@strong{Win32:} Since @code{strerror()} is not supported, the additional
|
||
|
last-chance translation described above cannot be performed.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
The returned pointer points to per-thread static storage, which can be
|
||
|
overwritten by subsequent calls to this function.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
|
||
|
@node ChfBuildMessage(), , ChfGetMessage(), Retrieving a message
|
||
|
@subsection ChfBuildMessage()
|
||
|
@deftypefn Function {char *} ChfBuildMessage (const ChfDescriptor *descriptor)
|
||
|
|
||
|
This function builds the message associated with the given condition
|
||
|
descriptor and returns a pointer to a string containing it.
|
||
|
|
||
|
The message has a standard format and provides the following information
|
||
|
items:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
The application's name given to the Chf library during initialization, if
|
||
|
the condition is the topmost within a condition group; otherwise, the message
|
||
|
starts with an horizontal tab character.
|
||
|
@item
|
||
|
The name of the module that generated the condition.
|
||
|
@item
|
||
|
If available, the file name and line number of the source where the condition
|
||
|
was generated.
|
||
|
@item
|
||
|
The severity code of the message.
|
||
|
@item
|
||
|
The message associated with the condition code, including any ancillary
|
||
|
information provided during condition generation.
|
||
|
@end itemize
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
if Chf hasn't been correctly initialized.
|
||
|
|
||
|
@item
|
||
|
The returned pointer points to per-thread static storage, which can be
|
||
|
overwritten by subsequent calls to this function.
|
||
|
|
||
|
@item
|
||
|
@strong{Win32:} to save space, the application's name and severity code
|
||
|
are not included in the message.
|
||
|
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@node Reserved module identifiers, Defining a new message retrieval subsystem, Retrieving a message, Message retrieval
|
||
|
@section Reserved module identifiers
|
||
|
@cindex Reserved module identifiers
|
||
|
|
||
|
The following module identifiers are currently used by the Chf library;
|
||
|
all module identifiers with value less than 10 are reserved for future use.
|
||
|
|
||
|
@table @code
|
||
|
@item 1
|
||
|
This module identifier is used as a message set identifier to retrieve the
|
||
|
names of the other application's modules. In particular, to retrieve the
|
||
|
name of the application's module @code{m}, the message @code{m} of
|
||
|
message set @code{1} is retrieved.
|
||
|
|
||
|
@item 2
|
||
|
This module identifier is used to identify the conditions generated by
|
||
|
the Chf library itself.
|
||
|
|
||
|
@item 3
|
||
|
This module identifier is used as a message set identifier to retrieve the
|
||
|
messages associated with the @code{errno} error codes. If the retrieve is
|
||
|
unsuccessful, @code{strerror()} is used instead.
|
||
|
@end table
|
||
|
|
||
|
@strong{Win32:} In addition, the current implementation of the
|
||
|
message retrieval subsystem on Win32 imposes the following limits:
|
||
|
@code{0 <= condition_code <= 999}, @code{0 <= module_id <= 64}.
|
||
|
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c Completed section on defining a new mrs
|
||
|
@node Defining a new message retrieval subsystem, , Reserved module identifiers, Message retrieval
|
||
|
@section Defining a new message retrieval subsystem
|
||
|
@cindex Defining a new message retrieval subsystem
|
||
|
|
||
|
The Chf library has a generic interface towards the message retrieval
|
||
|
subsystem (MRS); therefore, any subsystem can be used, provided it follows
|
||
|
the guidelines described below:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
A copy of the @code{mrs_data} argument of @code{ChfInit()} is passed to
|
||
|
each MRS function when it is invoked. It can be used to hold a pointer
|
||
|
to a private MRS data structures.
|
||
|
@item
|
||
|
The @code{mrs_get} function has the following arguments:
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
A copy of the @code{mrs_data} argument of @code{ChfInit()}.
|
||
|
@item
|
||
|
An @code{int}, representing the module identifier of the condition message
|
||
|
template/fragment to be retrieved.
|
||
|
@item
|
||
|
An @code{int}, representing the condition code of the condition message
|
||
|
template/fragment to be retrieved.
|
||
|
@item
|
||
|
A @code{char *}, pointing to a default message template/fragment to
|
||
|
be returned if the message retrieval fails.
|
||
|
@end itemize
|
||
|
The function must attempt to retrieve the message template/fragment
|
||
|
associated with the pair (module identifier, condition code) and return
|
||
|
it to the caller; if the retrieval fails, the default message must be
|
||
|
returned instead.
|
||
|
@item
|
||
|
The @code{mrs_exit} function is invoked when Chf is about to exit.
|
||
|
It has as argument a copy of the @code{mrs_data} argument or
|
||
|
@code{ChfInit()} and must perform any cleanup operation the MRS
|
||
|
needs. It is guaranteed that no other MRS function will be called
|
||
|
after a successful invocation of @code{mrs_exit}.
|
||
|
@item
|
||
|
When multithreading support is enabled, the MRS must support multiple,
|
||
|
concurrent invocations made by different application's threads. The same
|
||
|
value of @code{mrs_data} is common to all threads and cannot be changed
|
||
|
after initialization.
|
||
|
@end itemize
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c New chapter on multithreading support; revised all other chapters to
|
||
|
@c take multithreading support into account, too.
|
||
|
@node Multithreading support, Other useful macro definitions, Message retrieval, Top
|
||
|
@chapter Multithreading support
|
||
|
@cindex Multithreading support
|
||
|
|
||
|
When compiled appropriately, the Chf library supports multithreading,
|
||
|
and maintains one Chf context per active thread. Multithreading support
|
||
|
is enabled when the cpp macro @code{_REENTRANT} is defined.
|
||
|
|
||
|
@strong{Win32:} Multitreading support is not provided yet.
|
||
|
|
||
|
When multithreading support is enabled, the following modifications
|
||
|
to the default Chf behavior come into effect:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
@code{ChfInit()} no longer initializes the condition stack, the
|
||
|
condition handler stack and the message buffer immediately; instead, one
|
||
|
copy of these context elements will be allocated for each active thread
|
||
|
in the application, when it first invokes any other Chf function.
|
||
|
Also, per-thread Chf contexts are dynamically destroyed when the
|
||
|
owning thread terminates.
|
||
|
@item
|
||
|
Condition generation and both general and structured condition handling
|
||
|
work as before inside each application's thread. All threads share the
|
||
|
same values for @code{condition_stack_size}, @code{handler_stack_size}
|
||
|
and @code{exit_code}, but are otherwise fully independent with
|
||
|
respect to condition handling, because each of them has a private
|
||
|
Chf context.
|
||
|
@item
|
||
|
@code{ChfAbort()} no longer exits the whole application when
|
||
|
the @code{CHF_ABORT} Chf flag not set; instead, it exits the
|
||
|
invoking thread only.
|
||
|
@item
|
||
|
Almost all Chf functions can trigger the @code{CHF_ABORT_GET_CONTEXT}
|
||
|
and @code{CHF_ABORT_PTHREAD} aborts, if they fail to correctly
|
||
|
manage dynamic Chf context creation and/or @code{pthread} interactions.
|
||
|
@item
|
||
|
All Chf functions, except @code{ChfInit()} and @code{ChfExit()}
|
||
|
no longer check whether Chf has been correctly initialized or not:
|
||
|
that check would have been too time-consuming in a multithreaded environment.
|
||
|
As a consequence, invoking a Chf function when Chf has not been correctly
|
||
|
initialized has unpredictable effects instead of neatly aborting
|
||
|
the application with abort code @code{CHF_ABORT_INIT}.
|
||
|
@item
|
||
|
The performance of the Chf condition generation and signaling functions
|
||
|
is likely to decrease, because Chf must retrieve its per-thread context
|
||
|
dynamically instead of referring to a static storage area.
|
||
|
@end itemize
|
||
|
|
||
|
@node Other useful macro definitions, Other useful functions, Multithreading support, Top
|
||
|
@chapter Other useful macro definitions
|
||
|
@cindex Other useful macro definitions
|
||
|
|
||
|
@deftypefn Macro {} CHF_MAX_MESSAGE_LENGTH
|
||
|
Represents the maximum allowable length for condition messages.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_LIBRARY_ID
|
||
|
It is a string representing the Chf library identifier; the identifier
|
||
|
contains also the library release number.
|
||
|
@end deftypefn
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c New macros
|
||
|
@deftypefn Macro {} CHF_MAJOR_RELEASE_NUMBER
|
||
|
It is an integer representing the Chf library major release number.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_MINOR_RELEASE_NUMBER
|
||
|
It is an integer representing the Chf library minor release number.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_MODULE_NAMES_SET
|
||
|
Contains the integer identifier of the message set whose messages are used to
|
||
|
retrieve the names of the application's modules. It has the value 1.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_SET
|
||
|
Contains the integer identifier of the message set containing the condition
|
||
|
messages Chf uses internally. It has the value 2.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} CHF_ERRNO_SET
|
||
|
Contains the integer identifier of the message set containing the condition
|
||
|
messages for @code{errno} codes. It has the value 3.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} ChfChar
|
||
|
This macro is used to make portable declarations of character variables,
|
||
|
and is mapped into either @code{char} or @code{TCHAR} depending on the
|
||
|
platform.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} ChfText (x)
|
||
|
This macro is used to make portable declarations of character strings,
|
||
|
and is mapped into either @code{x} or @code{_T(x)} depending on the
|
||
|
platform.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} ChfSigjmp_buf
|
||
|
This macro is mapped into either @code{sigjmp_buf} or @code{jmp_buf},
|
||
|
depending on whether the platform supports @code{sigjmp_buf}
|
||
|
contexts or not.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} ChfSigsetjmp (x,y)
|
||
|
This macro is mapped into either @code{sigsetjmp()} or @code{setjmp()},
|
||
|
depending on whether the platform supports @code{sigjmp_buf}
|
||
|
contexts or not. In the latter case argument @code{x} is ignored.
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Macro {} ChfSiglongjmp (x,y)
|
||
|
This macro is mapped into either @code{siglongjmp()} or @code{longjmp()},
|
||
|
depending on whether the platform supports @code{sigjmp_buf}
|
||
|
contexts or not.
|
||
|
@end deftypefn
|
||
|
|
||
|
@node Other useful functions, Changes since release 1, Other useful macro definitions, Top
|
||
|
@chapter Other useful functions
|
||
|
@cindex Other useful functions
|
||
|
|
||
|
@deftypefn Function void ChfDiscard (void)
|
||
|
This function discards the topmost condition group currently in the
|
||
|
condition stack, without signaling it. The function does nothing if
|
||
|
the condition stack is empty.
|
||
|
|
||
|
This function uses the function @code{ChfAbort()} to
|
||
|
abort the application if Chf has not been initialized correctly
|
||
|
(abort code @code{CHF_ABORT_INIT}).
|
||
|
@end deftypefn
|
||
|
|
||
|
@deftypefn Function {const ChfDescriptor *} ChfGetTopCondition (void)
|
||
|
This function returns to the caller a pointer to the topmost condition of
|
||
|
the current condition group. It generates and immediately signals the
|
||
|
condition @code{CHF_F_BAD_STATE} if the current condition group is empty.
|
||
|
|
||
|
This function can be useful to retrieve the complete description of a
|
||
|
condition for functions that, when an error occurs, generate a condition
|
||
|
and return to the caller a generic error indication, such as a distinguished
|
||
|
return value.
|
||
|
|
||
|
The same function can also be useful in a structured exception handler,
|
||
|
to retrieve the condition descriptor associated with the exception to
|
||
|
be handled.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
During condition signaling, Chf creates a new, empty, condition group
|
||
|
immediately before starting the invocation sequence of the condition
|
||
|
handlers, as previously described. Therefore
|
||
|
@code{ChfGetTopCondition()}, when called from a condition handler, will return
|
||
|
a pointer to the top condition generated during the handling ONLY, if any, and
|
||
|
NOT to the top condition of the condition group being signaled. The
|
||
|
latter pointer is directly available, as an argument, to condition
|
||
|
handlers.
|
||
|
@item
|
||
|
When called from a structured exception handler, @code{ChfGetTopCondition()}
|
||
|
works as expected, that is, it returns a pointer to the top condition of
|
||
|
the condition group associated with the exception being handled.
|
||
|
@item
|
||
|
This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT}
|
||
|
if Chf hasn't been correctly initialized.
|
||
|
@item
|
||
|
The returned pointer is no longer valid when any other Chf function
|
||
|
is called after @code{ChfGetTopCondition()}.
|
||
|
@end itemize
|
||
|
@end deftypefn
|
||
|
|
||
|
@c 2.1, cibrario, 18-May-2000
|
||
|
@c New chapter on changes since release 1
|
||
|
@node Changes since release 1, Changes since release 2.1, Other useful functions, Top
|
||
|
@chapter Changes since release 1
|
||
|
@cindex Changes since release 1
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Chf now supports structured condition handling.
|
||
|
@xref{Structured condition handling}.
|
||
|
@item
|
||
|
Chf now supports multithreaded applications; each thread has its own Chf
|
||
|
context. Multithreading support is conditionally enabled by linking a
|
||
|
multithreaded version of the Chf library.
|
||
|
@xref{Multithreading support}.
|
||
|
@item
|
||
|
Chf now supports the conditional save and restore of signal masks in unwind
|
||
|
contexts (@code{sigjmp_buf} contexts instead of @code{jmp_buf}).
|
||
|
@item
|
||
|
The method of passing unwind contexts as arguments is now consistent
|
||
|
with that used by @code{sigsetjmp()}; in particular, it is no longer
|
||
|
necessary to reference the contexts with @code{&}.
|
||
|
@item
|
||
|
Some more useful macro definitions have been added to @code{Chf.h}.
|
||
|
@xref{Other useful macro definitions}.
|
||
|
@end itemize
|
||
|
|
||
|
@c 2.2, cibrario, 25-Jan-2001
|
||
|
@c New chapter on changes since release 2.1
|
||
|
@node Changes since release 2.1, Function Index, Changes since release 1, Top
|
||
|
@chapter Changes since release 2.1
|
||
|
@cindex Changes since release 2.1
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Chf now offers limited support of Unicode-based Win32 platforms,
|
||
|
notably Windows CE.
|
||
|
@end itemize
|
||
|
|
||
|
@node Function Index, Data Type Index, Changes since release 2.1, Top
|
||
|
@unnumbered Function Index
|
||
|
@printindex fn
|
||
|
|
||
|
@node Data Type Index, Concept Index, Function Index, Top
|
||
|
@unnumbered Data Type Index
|
||
|
@printindex tp
|
||
|
|
||
|
@c @node Variable Index, Concept Index, Data Type Index, Top
|
||
|
@c @unnumbered Variable Index
|
||
|
@c @printindex vr
|
||
|
|
||
|
@node Concept Index, , Data Type Index, Top
|
||
|
@unnumbered Concept Index
|
||
|
@printindex cp
|
||
|
|
||
|
@contents
|
||
|
|
||
|
@bye
|