Emacs Lisp supports nonlocal exits, whereby program control is
transferred from one point in a program to another remote point.
See Nonlocal Exits. Thus, Lisp functions called by your module
might exit nonlocally by calling signal
or throw
, and
your module functions must handle such nonlocal exits properly. Such
handling is needed because C programs will not automatically release
resources and perform other cleanups in these cases; your module code
must itself do it. The module API provides facilities for
that, described in this subsection. They are generally available
since Emacs 25; those of them that became available in later releases
explicitly call out the first Emacs version where they became part of
the API.
When some Lisp code called by a module function signals an error or
throws, the nonlocal exit is trapped, and the pending exit and its
associated data are stored in the environment. Whenever a nonlocal
exit is pending in the environment, any module API function
called with a pointer to that environment will return immediately
without any processing (the functions non_local_exit_check
,
non_local_exit_get
, and non_local_exit_clear
are
exceptions from this rule). If your module function then does nothing
and returns to Emacs, a pending nonlocal exit will cause Emacs to act
on it: signal an error or throw to the corresponding catch
.
So the simplest “handling” of nonlocal exits in module functions is to do nothing special and let the rest of your code to run as if nothing happened. However, this can cause two classes of problems:
Therefore, we recommend that your module functions check for nonlocal exit conditions and recover from them, using the functions described below.
enum emacs_funcall_exit
non_local_exit_check (emacs_env *env)
¶This function returns the kind of nonlocal exit condition stored in env. The possible values are:
enum emacs_funcall_exit
non_local_exit_get (emacs_env *env, emacs_value *symbol, emacs_value *data)
¶This function returns the kind of nonlocal exit condition stored in
env, like non_local_exit_check
does, but it also returns
the full information about the nonlocal exit, if any. If the return
value is emacs_funcall_exit_signal
, the function stores the
error symbol in *symbol
and the error data in
*data
(see How to Signal an Error). If the return value is
emacs_funcall_exit_throw
, the function stores the catch
tag symbol in *symbol
and the throw
value in
*data
. The function doesn’t store anything in memory
pointed by these arguments when the return value is
emacs_funcall_exit_return
.
You should check nonlocal exit conditions where it matters: before you allocated some resource or after you allocated a resource that might need freeing, or where a failure means further processing is impossible or infeasible.
Once your module function detected that a nonlocal exit is pending, it can either return to Emacs (after performing the necessary local cleanup), or it can attempt to recover from the nonlocal exit. The following API functions will help with these tasks.
void
non_local_exit_clear (emacs_env *env)
¶This function clears the pending nonlocal exit conditions and data from env. After calling it, the module API functions will work normally. Use this function if your module function can recover from nonlocal exits of the Lisp functions it calls and continue, and also before calling any of the following two functions (or any other API functions, if you want them to perform their intended processing when a nonlocal exit is pending).
void
non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
¶This function throws to the Lisp catch
symbol represented by
tag, passing it value as the value to return. Your module
function should in general return soon after calling this function.
One use of this function is when you want to re-throw a non-local exit
from one of the called API or Lisp functions.
void
non_local_exit_signal (emacs_env *env, emacs_value symbol, emacs_value data)
¶This function signals the error represented by the error symbol symbol with the specified error data data. The module function should return soon after calling this function. This function could be useful, e.g., for signaling errors from module functions to Emacs.