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.