mirror of
https://github.com/etlegacy/etlegacy-libs.git
synced 2024-11-10 23:01:47 +00:00
84 lines
3.3 KiB
ReStructuredText
84 lines
3.3 KiB
ReStructuredText
|
***********
|
||
|
Portability
|
||
|
***********
|
||
|
|
||
|
.. _portability-thread-safety:
|
||
|
|
||
|
Thread safety
|
||
|
-------------
|
||
|
|
||
|
Jansson is thread safe and has no mutable global state. The only
|
||
|
exceptions are the hash function seed and memory allocation functions,
|
||
|
see below.
|
||
|
|
||
|
There's no locking performed inside Jansson's code, so a multithreaded
|
||
|
program must perform its own locking if JSON values are shared by
|
||
|
multiple threads. Jansson's reference counting semantics may make this
|
||
|
a bit harder than it seems, as it's possible to have a reference to a
|
||
|
value that's also stored inside a list or object. Modifying the
|
||
|
container (adding or removing values) may trigger concurrent access to
|
||
|
such values, as containers manage the reference count of their
|
||
|
contained values. Bugs involving concurrent incrementing or
|
||
|
decrementing of deference counts may be hard to track.
|
||
|
|
||
|
The encoding functions (:func:`json_dumps()` and friends) track
|
||
|
reference loops by modifying the internal state of objects and arrays.
|
||
|
For this reason, encoding functions must not be run on the same JSON
|
||
|
values in two separate threads at the same time. As already noted
|
||
|
above, be especially careful if two arrays or objects share their
|
||
|
contained values with another array or object.
|
||
|
|
||
|
If you want to make sure that two JSON value hierarchies do not
|
||
|
contain shared values, use :func:`json_deep_copy()` to make copies.
|
||
|
|
||
|
|
||
|
Hash function seed
|
||
|
==================
|
||
|
|
||
|
To prevent an attacker from intentionally causing large JSON objects
|
||
|
with specially crafted keys to perform very slow, the hash function
|
||
|
used by Jansson is randomized using a seed value. The seed is
|
||
|
automatically generated on the first explicit or implicit call to
|
||
|
:func:`json_object()`, if :func:`json_object_seed()` has not been
|
||
|
called beforehand.
|
||
|
|
||
|
The seed is generated by using operating system's entropy sources if
|
||
|
they are available (``/dev/urandom``, ``CryptGenRandom()``). The
|
||
|
initialization is done in as thread safe manner as possible, by using
|
||
|
architecture specific lockless operations if provided by the platform
|
||
|
or the compiler.
|
||
|
|
||
|
If you're using threads, it's recommended to autoseed the hashtable
|
||
|
explicitly before spawning any threads by calling
|
||
|
``json_object_seed(0)`` , especially if you're unsure whether the
|
||
|
initialization is thread safe on your platform.
|
||
|
|
||
|
|
||
|
Memory allocation functions
|
||
|
===========================
|
||
|
|
||
|
Memory allocation functions should be set at most once, and only on
|
||
|
program startup. See :ref:`apiref-custom-memory-allocation`.
|
||
|
|
||
|
|
||
|
Locale
|
||
|
------
|
||
|
|
||
|
Jansson works fine under any locale.
|
||
|
|
||
|
However, if the host program is multithreaded and uses ``setlocale()``
|
||
|
to switch the locale in one thread while Jansson is currently encoding
|
||
|
or decoding JSON data in another thread, the result may be wrong or
|
||
|
the program may even crash.
|
||
|
|
||
|
Jansson uses locale specific functions for certain string conversions
|
||
|
in the encoder and decoder, and then converts the locale specific
|
||
|
values to/from the JSON representation. This fails if the locale
|
||
|
changes between the string conversion and the locale-to-JSON
|
||
|
conversion. This can only happen in multithreaded programs that use
|
||
|
``setlocale()``, because ``setlocale()`` switches the locale for all
|
||
|
running threads, not only the thread that calls ``setlocale()``.
|
||
|
|
||
|
If your program uses ``setlocale()`` as described above, consider
|
||
|
using the thread-safe ``uselocale()`` instead.
|