.. _thread-safety:

Thread Safety
=============

Per `libcurl thread safety documentation`_, libcurl is thread-safe but
has no internal thread synchronization.

For Python programs using PycURL, this means:

* Accessing the same PycURL object from different threads is OK when
  this object is not involved in active transfers, as Python internally
  has a Global Interpreter Lock and only one operating system thread can
  be executing Python code at a time.

* Accessing a PycURL object that is involved in an active transfer from
  Python code *inside a libcurl callback for the PycURL object in question*
  is OK, because PycURL takes out the appropriate locks.

* Accessing a PycURL object that is involved in an active transfer from
  Python code *outside of a libcurl callback for the PycURL object in question*
  is unsafe.

* Closing a ``CurlShare`` object with ``detach_on_close=True`` (the
  default) is **not thread-safe** with respect to the associated
  ``Curl`` objects. During ``CurlShare.close()``, PycURL automatically
  detaches all associated ``Curl`` objects by clearing their ``SHARE``
  option. The caller must ensure that no other thread is using the
  associated ``Curl`` objects while ``CurlShare.close()`` is executing.

* A WebSocket handle (``CONNECT_ONLY=2`` plus ``ws_send`` / ``ws_recv``)
  follows the same one-handle-one-thread rule: do not call ``ws_send``
  from one thread while ``ws_recv`` runs on another. Serialise access
  with a lock. Calls from another thread while ``perform()`` is running
  are unsafe unless they happen inside that handle's active
  ``WRITEFUNCTION`` callback.

PycURL handles the necessary SSL locks for OpenSSL/LibreSSL/BoringSSL,
GnuTLS, NSS, mbedTLS and wolfSSL.

A special situation exists when libcurl uses the standard C library
name resolver (i.e., not threaded nor c-ares resolver). By default libcurl
uses signals for timeouts with the C library resolver, and signals do not
work properly in multi-threaded programs. When using PycURL objects from
multiple Python threads ``NOSIGNAL`` option `must be given`_.

.. _libcurl thread safety documentation: https://curl.haxx.se/libcurl/c/threadsafe.html
.. _must be given: https://github.com/curl/curl/issues/1003
