saturnng/libChf/docs/chf.texi

2054 lines
73 KiB
Text
Raw Normal View History

2022-03-21 11:05:59 +01:00
\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::
2022-03-21 11:05:59 +01:00
* Concept Index::
@c @detailmenu --- The Detailed Node Listing ---
Initialization and exit
* ChfInit()::
* ChfMsgcatInit()::
* ChfStaticInit()::
* ChfWin32Init()::
* ChfExit()::
* ChfAbort()::
* Library header::
2022-03-21 11:05:59 +01:00
Condition generation and signal
* Generating a condition::
* Signaling a condition::
2022-03-21 11:05:59 +01:00
Generating a condition
* ChfCondition::
* ChfEnd::
* ChfSeverity::
* ChfErrnoCondition::
2022-03-21 11:05:59 +01:00
Signaling a condition
* ChfSignal()::
2022-03-21 11:05:59 +01:00
Condition handling
* Condition handlers::
* Condition descriptors::
* Condition handling state::
* Handler actions::
* Default handler::
2022-03-21 11:05:59 +01:00
Condition handlers
* ChfHandler::
* ChfPushHandler()::
* ChfPopHandler()::
2022-03-21 11:05:59 +01:00
Structured condition handling
* Syntax of structured condition handlers::
* Chf behavior during structured condition handling::
2022-03-21 11:05:59 +01:00
Chf behavior during structured condition handling
* ChfTry::
* ChfCatch::
* ChfEndTry::
2022-03-21 11:05:59 +01:00
Message retrieval
* Retrieving a message::
* Reserved module identifiers::
* Defining a new message retrieval subsystem::
2022-03-21 11:05:59 +01:00
Retrieving a message
* ChfGetMessage()::
* ChfBuildMessage()::
2022-03-21 11:05:59 +01:00
@c @end detailmenu
@end menu
@node Overview, Initialization and exit, Top, Top
@chapter Overview
@cindex Overview
@cindex Win32 Support
The Condition Handling facility library
2022-03-21 11:05:59 +01:00
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::
2022-03-21 11:05:59 +01:00
@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.
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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()::
2022-03-21 11:05:59 +01:00
@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:
@itemize @bullet
2022-03-21 11:05:59 +01:00
@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 itemize
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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()::
2022-03-21 11:05:59 +01:00
@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.
2022-03-21 11:05:59 +01:00
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.
2022-03-21 11:05:59 +01:00
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)
2022-03-21 11:05:59 +01:00
@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
2022-03-21 11:05:59 +01:00
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:
@itemize @bullet
2022-03-21 11:05:59 +01:00
@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 itemize
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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::
2022-03-21 11:05:59 +01:00
@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()::
2022-03-21 11:05:59 +01:00
@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