========================================
Footguns
========================================

This section notes areas where certain usages can cause confusing bugs or problems.

Static Objects
------------------

If you maintain ``static`` variables which hold Botan objects, you will perhaps
find that in some circumstances your application crashes in strange ways on
shutdown. That is because, at least on some operating systems, Botan uses a
locked memory pool as backing storage for the ``secure_vector`` type. This pool
allocates out of pages which have been locked into memory using ``mlock`` or
``VirtualLock`` system calls.

If your variable happens to be destroyed before the pool, all is well. If the
pool happens to be destroyed before the variable, then when the object goes to
free its memory, a crash will occur.

This is basically the famous C++ "Static Initialization Order Fiasco", except
in reverse.

The best course of action is to avoid ``static`` variables. If that is
impossible or inconvenient, one option is to disable the pool, either at build
time (disable the ``locking_allocator`` module) or at runtime. Unfortunately the
runtime setting requires setting an environment variable (see :ref:`env_vars`),
and doing so consistently *prior to static initialization* is not trivial, due to
the previously mentioned fiasco. One option might be to use GCC's
``constructor`` function attribute.

Another approach is to use the utility class ``Allocator_Initializer`` (declared
in ``mem_ops.h``) as an associated ``static`` variable in your code. As long as
the ``Allocator_Initializer`` is created *before* your static variables, that
means the allocator is created before your object, and thus will be destroyed
after your object is destroyed.

Ideally a more satisfactory solution to this issue could be found, especially
given the difficulty of disabling the pool at runtime.

Multithreaded Access
----------------------

It is perfectly safe to use the library from multiple threads.

It is *not* safe to use the same object from multiple threads, without some form
of external serialization or locking.

There are a few exceptions to this rule, where the type itself maintains an
internal mutexes. This will be noted in the respective documentation for that type.

Use of `fork`
----------------------

If you use the `fork` syscall in your code, and attempt to use the library in
both processes, likely bad things will happen due to internal locks. You can
avoid this problem by either at build time disabling the features associated
with these locks (namely ``locking_allocator`` and ``thread_utils``) or
disabling them at runtime using :ref:`env_vars`, ideally at the very start of
`main`.
