4.11.1 Urgency of exceptions
Under some conditions an exception may be raised as a result of handling another exception. Below are some of the scenarios:
- The predicate setup_call_cleanup/3 calls the cleanup handler as a result of an exception and the cleanup handler raises an exception itself. In this case the most urgent exception is propagated into the environment.
- Raising an exception fails due to lack of resources, e.g., lack of
stack space to store the exception. In this case a resource exception is
raised. If that too fails the system tries to raise a resource exception
without (stack) context. If that fails it will raise the exception
'$aborted'
, also raised by abort/0. As no stack space is required for processing this atomic exception, this should always succeed. - Certain callback operations raise an exception while processing another exception or a previous callback already raised an exception before there was an opportunity to process the exception. The most notable callback subject to this issue are prolog_event_hook/1 (supporting e.g., the graphical debugger), prolog_exception_hook/4 (rewriting exceptions, e.g., by adding context) and print_message/2 when called from the core facilities such as the internal debugger. As with setup_call_cleanup/3, the most urgent exception is preserved.
If the most urgent exceptions needs to be preserved, the following exception ordering is respected, preserving the topmost matching error.
'$aborted'
(abort/0)time_limit_exceeded
(call_with_time_limit/2)error(
resource_error(Resource)
, Context)error(Formal, Context)
- All other exceptions
Note The above resolution is not described in the ISO
standard. This is not needed either because ISO does not specify
setup_call_cleanup/3
and does not deal with environment management issues such as (debugger)
callbacks. Neither does it define abort/0
or timeout handling. Notably abort/0
and timeout are non-logical control structures. They are implemented on
top of exceptions as they need to unwind the stack, destroy choice
points and call cleanup handlers in the same way. However, the pending
exception should not be replaced by another one before the intended
handler is reached. The abort exception cannot be caught, something
which is achieved by wrapping the cleanup handler of catch/3
into
call_cleanup(Handler, abort)
.