Thread states and the global interpreter lock¶
Unless on afree-threaded build ofCPython,the Python interpreter is not fully thread-safe. In order to supportmulti-threaded Python programs, there’s a global lock, called theglobalinterpreter lock orGIL, that must be held by the current thread beforeit can safely access Python objects. Without the lock, even the simplestoperations could cause problems in a multi-threaded program: for example, whentwo threads simultaneously increment the reference count of the same object, thereference count could end up being incremented only once instead of twice.
Therefore, the rule exists that only the thread that has acquired theGIL may operate on Python objects or call Python/C API functions.In order to emulate concurrency of execution, the interpreter regularlytries to switch threads (seesys.setswitchinterval()). The lock is alsoreleased around potentially blocking I/O operations like reading or writinga file, so that other Python threads can run in the meantime.
The Python interpreter keeps some thread-specific bookkeeping informationinside a data structure calledPyThreadState, known as athread state.Each OS thread has a thread-local pointer to aPyThreadState; a thread statereferenced by this pointer is considered to beattached.
A thread can only have oneattached thread state at a time. An attachedthread state is typically analogous with holding theGIL, except onfree-threaded builds. On builds with theGIL enabled,attaching a thread state will block until theGILcan be acquired. However, even on builds with theGIL disabled, it is still requiredto have an attached thread state to call most of the C API.
In general, there will always be anattached thread state when using Python’s C API.Only in some specific cases (such as in aPy_BEGIN_ALLOW_THREADS block) will thethread not have an attached thread state. If uncertain, check ifPyThreadState_GetUnchecked() returnsNULL.
Detaching the thread state from extension code¶
Most extension code manipulating thethread state has the following simplestructure:
Savethethreadstateinalocalvariable....DosomeblockingI/Ooperation...Restorethethreadstatefromthelocalvariable.
This is so common that a pair of macros exists to simplify it:
Py_BEGIN_ALLOW_THREADS...DosomeblockingI/Ooperation...Py_END_ALLOW_THREADS
ThePy_BEGIN_ALLOW_THREADS macro opens a new block and declares ahidden local variable; thePy_END_ALLOW_THREADS macro closes theblock.
The block above expands to the following code:
PyThreadState*_save;_save=PyEval_SaveThread();...DosomeblockingI/Ooperation...PyEval_RestoreThread(_save);
Here is how these functions work:
Theattached thread state holds theGIL for the entire interpreter. When detachingtheattached thread state, theGIL is released, allowing other threads to attacha thread state to their own thread, thus getting theGIL and can start executing.The pointer to the priorattached thread state is stored as a local variable.Upon reachingPy_END_ALLOW_THREADS, the thread state that waspreviouslyattached is passed toPyEval_RestoreThread().This function will block until another releases itsthread state,thus allowing the oldthread state to get re-attached and theC API can be called again.
Forfree-threaded builds, theGIL is normallyout of the question, but detaching thethread state is still requiredfor blocking I/O and long operations. The difference is that threads don’t have to wait for theGILto be released to attach their thread state, allowing true multi-core parallelism.
Note
Calling system I/O functions is the most common use case for detachingthethread state, but it can also be useful before callinglong-running computations which don’t need access to Python objects, suchas compression or cryptographic functions operating over memory buffers.For example, the standardzlib andhashlib modules detach thethread state when compressing or hashing data.
APIs¶
The following macros are normally used without a trailing semicolon; look forexample usage in the Python source distribution.
Note
These macros are still necessary on thefree-threaded build to preventdeadlocks.
- Py_BEGIN_ALLOW_THREADS¶
- Part of theStable ABI.
This macro expands to
{PyThreadState*_save;_save=PyEval_SaveThread();.Note that it contains an opening brace; it must be matched with a followingPy_END_ALLOW_THREADSmacro. See above for further discussion of thismacro.
- Py_END_ALLOW_THREADS¶
- Part of theStable ABI.
This macro expands to
PyEval_RestoreThread(_save);}. Note that it containsa closing brace; it must be matched with an earlierPy_BEGIN_ALLOW_THREADSmacro. See above for further discussion ofthis macro.
- Py_BLOCK_THREADS¶
- Part of theStable ABI.
This macro expands to
PyEval_RestoreThread(_save);: it is equivalent toPy_END_ALLOW_THREADSwithout the closing brace.
- Py_UNBLOCK_THREADS¶
- Part of theStable ABI.
This macro expands to
_save=PyEval_SaveThread();: it is equivalent toPy_BEGIN_ALLOW_THREADSwithout the opening brace and variabledeclaration.
Non-Python created threads¶
When threads are created using the dedicated Python APIs (such as thethreading module), a thread state is automatically associated to themand the code shown above is therefore correct. However, when threads arecreated from C (for example by a third-party library with its own threadmanagement), they don’t hold theGIL, because they don’t have anattached thread state.
If you need to call Python code from these threads (often this will be partof a callback API provided by the aforementioned third-party library),you must first register these threads with the interpreter bycreating anattached thread state before you can start using the Python/CAPI. When you are done, you should detach thethread state, andfinally free it.
ThePyGILState_Ensure() andPyGILState_Release() functions doall of the above automatically. The typical idiom for calling into Pythonfrom a C thread is:
PyGILState_STATEgstate;gstate=PyGILState_Ensure();/* Perform Python actions here. */result=CallSomeFunction();/* evaluate result or handle exception *//* Release the thread. No Python API allowed beyond this point. */PyGILState_Release(gstate);
Note that thePyGILState_* functions assume there is only one globalinterpreter (created automatically byPy_Initialize()). Pythonsupports the creation of additional interpreters (usingPy_NewInterpreter()), but mixing multiple interpreters and thePyGILState_* API is unsupported. This is becausePyGILState_Ensure()and similar functions default toattaching athread state for the main interpreter, meaning that the thread can’t safelyinteract with the calling subinterpreter.
Supporting subinterpreters in non-Python threads¶
If you would like to support subinterpreters with non-Python created threads, youmust use thePyThreadState_* API instead of the traditionalPyGILState_*API.
In particular, you must store the interpreter state from the callingfunction and pass it toPyThreadState_New(), which will ensure thatthethread state is targeting the correct interpreter:
/* The return value of PyInterpreterState_Get() from the function that created this thread. */PyInterpreterState*interp=ThreadData->interp;PyThreadState*tstate=PyThreadState_New(interp);PyThreadState_Swap(tstate);/* GIL of the subinterpreter is now held. Perform Python actions here. */result=CallSomeFunction();/* evaluate result or handle exception *//* Destroy the thread state. No Python API allowed beyond this point. */PyThreadState_Clear(tstate);PyThreadState_DeleteCurrent();
Cautions about fork()¶
Another important thing to note about threads is their behaviour in the faceof the Cfork() call. On most systems withfork(), after aprocess forks only the thread that issued the fork will exist. This has aconcrete impact both on how locks must be handled and on all stored statein CPython’s runtime.
The fact that only the “current” thread remainsmeans any locks held by other threads will never be released. Python solvesthis foros.fork() by acquiring the locks it uses internally beforethe fork, and releasing them afterwards. In addition, it resets anyLock objects in the child. When extending or embedding Python, thereis no way to inform Python of additional (non-Python) locks that need to beacquired before or reset after a fork. OS facilities such aspthread_atfork() would need to be used to accomplish the same thing.Additionally, when extending or embedding Python, callingfork()directly rather than throughos.fork() (and returning to or callinginto Python) may result in a deadlock by one of Python’s internal locksbeing held by a thread that is defunct after the fork.PyOS_AfterFork_Child() tries to reset the necessary locks, but is notalways able to.
The fact that all other threads go away also means that CPython’sruntime state there must be cleaned up properly, whichos.fork()does. This means finalizing all otherPyThreadState objectsbelonging to the current interpreter and all otherPyInterpreterState objects. Due to this and the specialnature of the“main” interpreter,fork() should only be called in that interpreter’s “main”thread, where the CPython global runtime was originally initialized.The only exception is ifexec() will be called immediatelyafter.
High-level APIs¶
These are the most commonly used types and functions when writing multi-threadedC extensions.
- typePyThreadState¶
- Part of theLimited API (as an opaque struct).
This data structure represents the state of a single thread. The only publicdata member is:
- PyInterpreterState*interp¶
This thread’s interpreter state.
- PyInterpreterState*interp¶
- voidPyEval_InitThreads()¶
- Part of theStable ABI.
Deprecated function which does nothing.
In Python 3.6 and older, this function created the GIL if it didn’t exist.
Changed in version 3.9:The function now does nothing.
Changed in version 3.7:This function is now called by
Py_Initialize(), so you don’thave to call it yourself anymore.Changed in version 3.2:This function cannot be called before
Py_Initialize()anymore.Deprecated since version 3.9.
- PyThreadState*PyEval_SaveThread()¶
- Part of theStable ABI.
Detach theattached thread state and return it.The thread will have nothread state upon returning.
- voidPyEval_RestoreThread(PyThreadState*tstate)¶
- Part of theStable ABI.
Set theattached thread state totstate.The passedthread stateshould not beattached,otherwise deadlock ensues.tstate will be attached upon returning.
Note
Calling this function from a thread when the runtime is finalizing willhang the thread until the program exits, even if the thread was notcreated by Python. Refer toCautions regarding runtime finalization for more details.
Changed in version 3.14:Hangs the current thread, rather than terminating it, if called while theinterpreter is finalizing.
- PyThreadState*PyThreadState_Get()¶
- Part of theStable ABI.
Return theattached thread state. If the thread has no attachedthread state, (such as when inside of
Py_BEGIN_ALLOW_THREADSblock), then this issues a fatal error (so that the caller needn’t checkforNULL).See also
PyThreadState_GetUnchecked().
- PyThreadState*PyThreadState_GetUnchecked()¶
Similar to
PyThreadState_Get(), but don’t kill the process with afatal error if it is NULL. The caller is responsible to check if the resultis NULL.Added in version 3.13:In Python 3.5 to 3.12, the function was private and known as
_PyThreadState_UncheckedGet().
- PyThreadState*PyThreadState_Swap(PyThreadState*tstate)¶
- Part of theStable ABI.
Set theattached thread state totstate, and return thethread state that was attached prior to calling.
This function is safe to call without anattached thread state; itwill simply return
NULLindicating that there was no prior thread state.See also
Note
Similar to
PyGILState_Ensure(), this function will hang thethread if the runtime is finalizing.
GIL-state APIs¶
The following functions use thread-local storage, and are not compatiblewith sub-interpreters:
- typePyGILState_STATE¶
- Part of theStable ABI.
The type of the value returned by
PyGILState_Ensure()and passed toPyGILState_Release().- enumeratorPyGILState_LOCKED¶
The GIL was already held when
PyGILState_Ensure()was called.
- enumeratorPyGILState_UNLOCKED¶
The GIL was not held when
PyGILState_Ensure()was called.
- enumeratorPyGILState_LOCKED¶
- PyGILState_STATEPyGILState_Ensure()¶
- Part of theStable ABI.
Ensure that the current thread is ready to call the Python C API regardlessof the current state of Python, or of theattached thread state. This maybe called as many times as desired by a thread as long as each call ismatched with a call to
PyGILState_Release(). In general, otherthread-related APIs may be used betweenPyGILState_Ensure()andPyGILState_Release()calls as long as the thread state is restored toits previous state before the Release(). For example, normal usage of thePy_BEGIN_ALLOW_THREADSandPy_END_ALLOW_THREADSmacros isacceptable.The return value is an opaque “handle” to theattached thread state when
PyGILState_Ensure()was called, and must be passed toPyGILState_Release()to ensure Python is left in the same state. Eventhough recursive calls are allowed, these handlescannot be shared - eachunique call toPyGILState_Ensure()must save the handle for its calltoPyGILState_Release().When the function returns, there will be anattached thread stateand the thread will be able to call arbitrary Python code. Failure is a fatal error.
Warning
Calling this function when the runtime is finalizing is unsafe. Doingso will either hang the thread until the program ends, or fully crashthe interpreter in rare cases. Refer toCautions regarding runtime finalization for more details.
Changed in version 3.14:Hangs the current thread, rather than terminating it, if called while theinterpreter is finalizing.
- voidPyGILState_Release(PyGILState_STATE)¶
- Part of theStable ABI.
Release any resources previously acquired. After this call, Python’s state willbe the same as it was prior to the corresponding
PyGILState_Ensure()call(but generally this state will be unknown to the caller, hence the use of theGILState API).Every call to
PyGILState_Ensure()must be matched by a call toPyGILState_Release()on the same thread.
- PyThreadState*PyGILState_GetThisThreadState()¶
- Part of theStable ABI.
Get theattached thread state for this thread. May return
NULLif noGILState API has been used on the current thread. Note that the main threadalways has such a thread-state, even if no auto-thread-state call has beenmade on the main thread. This is mainly a helper/diagnostic function.Note
This function may return non-
NULLeven when thethread stateis detached.PreferPyThreadState_Get()orPyThreadState_GetUnchecked()for most cases.See also
- intPyGILState_Check()¶
Return
1if the current thread is holding theGIL and0otherwise.This function can be called from any thread at any time.Only if it has had itsthread state initializedviaPyGILState_Ensure()will it return1.This is mainly a helper/diagnostic function. It can be usefulfor example in callback contexts or memory allocation functions whenknowing that theGIL is locked can allow the caller to perform sensitiveactions or otherwise behave differently.Note
If the current Python process has ever created a subinterpreter, thisfunction willalways return
1. PreferPyThreadState_GetUnchecked()for most cases.Added in version 3.4.
Low-level APIs¶
- PyThreadState*PyThreadState_New(PyInterpreterState*interp)¶
- Part of theStable ABI.
Create a new thread state object belonging to the given interpreter object.Anattached thread state is not needed.
- voidPyThreadState_Clear(PyThreadState*tstate)¶
- Part of theStable ABI.
Reset all information in athread state object.tstatemust beattached
Changed in version 3.9:This function now calls the
PyThreadState.on_deletecallback.Previously, that happened inPyThreadState_Delete().Changed in version 3.13:The
PyThreadState.on_deletecallback was removed.
- voidPyThreadState_Delete(PyThreadState*tstate)¶
- Part of theStable ABI.
Destroy athread state object.tstate should notbeattached to any thread.tstate must have been reset with a previous call to
PyThreadState_Clear().
- voidPyThreadState_DeleteCurrent(void)¶
Detach theattached thread state (which must have been resetwith a previous call to
PyThreadState_Clear()) and then destroy it.Nothread state will beattached uponreturning.
- PyFrameObject*PyThreadState_GetFrame(PyThreadState*tstate)¶
- Part of theStable ABI since version 3.10.
Get the current frame of the Python thread statetstate.
Return astrong reference. Return
NULLif no frame is currentlyexecuting.See also
PyEval_GetFrame().tstate must not be
NULL, and must beattached.Added in version 3.9.
- uint64_tPyThreadState_GetID(PyThreadState*tstate)¶
- Part of theStable ABI since version 3.10.
Get the uniquethread state identifier of the Python thread statetstate.
tstate must not be
NULL, and must beattached.Added in version 3.9.
- PyInterpreterState*PyThreadState_GetInterpreter(PyThreadState*tstate)¶
- Part of theStable ABI since version 3.10.
Get the interpreter of the Python thread statetstate.
tstate must not be
NULL, and must beattached.Added in version 3.9.
- voidPyThreadState_EnterTracing(PyThreadState*tstate)¶
Suspend tracing and profiling in the Python thread statetstate.
Resume them using the
PyThreadState_LeaveTracing()function.Added in version 3.11.
- voidPyThreadState_LeaveTracing(PyThreadState*tstate)¶
Resume tracing and profiling in the Python thread statetstate suspendedby the
PyThreadState_EnterTracing()function.See also
PyEval_SetTrace()andPyEval_SetProfile()functions.Added in version 3.11.
- intPyUnstable_ThreadState_SetStackProtection(PyThreadState*tstate,void*stack_start_addr,size_tstack_size)¶
- This isUnstable API. It may change without warning in minor releases.
Set the stack protection start address and stack protection sizeof a Python thread state.
On success, return
0.On failure, set an exception and return-1.CPython implementsrecursion control for C code by raising
RecursionErrorwhen it notices that the machine execution stack is closeto overflow. See for example thePy_EnterRecursiveCall()function.For this, it needs to know the location of the current thread’s stack, which itnormally gets from the operating system.When the stack is changed, for example using context switching techniques like theBoost library’sboost::context, you must callPyUnstable_ThreadState_SetStackProtection()to inform CPython of the change.Call
PyUnstable_ThreadState_SetStackProtection()either beforeor after changing the stack.Do not call any other Python C API between the call and the stackchange.See
PyUnstable_ThreadState_ResetStackProtection()for undoing this operation.Added in version 3.15.
- voidPyUnstable_ThreadState_ResetStackProtection(PyThreadState*tstate)¶
- This isUnstable API. It may change without warning in minor releases.
Reset the stack protection start address and stack protection sizeof a Python thread state to the operating system defaults.
See
PyUnstable_ThreadState_SetStackProtection()for an explanation.Added in version 3.15.
- PyObject*PyThreadState_GetDict()¶
- Return value: Borrowed reference. Part of theStable ABI.
Return a dictionary in which extensions can store thread-specific stateinformation. Each extension should use a unique key to use to store state inthe dictionary. It is okay to call this function when nothread stateisattached. If this function returns
NULL, no exception has been raised and the caller should assume nothread state is attached.
- voidPyEval_AcquireThread(PyThreadState*tstate)¶
- Part of theStable ABI.
Attachtstate to the current thread,which must not be
NULLor alreadyattached.The calling thread must not already have anattached thread state.
Note
Calling this function from a thread when the runtime is finalizing willhang the thread until the program exits, even if the thread was notcreated by Python. Refer toCautions regarding runtime finalization for more details.
Changed in version 3.8:Updated to be consistent with
PyEval_RestoreThread(),Py_END_ALLOW_THREADS(), andPyGILState_Ensure(),and terminate the current thread if called while the interpreter is finalizing.Changed in version 3.14:Hangs the current thread, rather than terminating it, if called while theinterpreter is finalizing.
PyEval_RestoreThread()is a higher-level function which is alwaysavailable (even when threads have not been initialized).
- voidPyEval_ReleaseThread(PyThreadState*tstate)¶
- Part of theStable ABI.
Detach theattached thread state.Thetstate argument, which must not be
NULL, is only used to checkthat it represents theattached thread state — if it isn’t, a fatal error isreported.PyEval_SaveThread()is a higher-level function which is alwaysavailable (even when threads have not been initialized).
Asynchronous notifications¶
A mechanism is provided to make asynchronous notifications to the maininterpreter thread. These notifications take the form of a functionpointer and a void pointer argument.
- intPy_AddPendingCall(int(*func)(void*),void*arg)¶
- Part of theStable ABI.
Schedule a function to be called from the main interpreter thread. Onsuccess,
0is returned andfunc is queued for being called in themain thread. On failure,-1is returned without setting any exception.When successfully queued,func will beeventually called from themain interpreter thread with the argumentarg. It will be calledasynchronously with respect to normally running Python code, but withboth these conditions met:
on abytecode boundary;
with the main thread holding anattached thread state(func can therefore use the full C API).
func must return
0on success, or-1on failure with an exceptionset.func won’t be interrupted to perform another asynchronousnotification recursively, but it can still be interrupted to switchthreads if thethread state is detached.This function doesn’t need anattached thread state. However, to call thisfunction in a subinterpreter, the caller must have anattached thread state.Otherwise, the functionfunc can be scheduled to be called from the wrong interpreter.
Warning
This is a low-level function, only useful for very special cases.There is no guarantee thatfunc will be called as quick aspossible. If the main thread is busy executing a system call,func won’t be called before the system call returns. Thisfunction is generallynot suitable for calling Python code fromarbitrary C threads. Instead, use thePyGILState API.
Added in version 3.1.
Changed in version 3.9:If this function is called in a subinterpreter, the functionfunc isnow scheduled to be called from the subinterpreter, rather than beingcalled from the main interpreter. Each subinterpreter now has its ownlist of scheduled calls.
Changed in version 3.12:This function now always schedulesfunc to be run in the maininterpreter.
- intPy_MakePendingCalls(void)¶
- Part of theStable ABI.
Execute all pending calls. This is usually executed automatically by theinterpreter.
This function returns
0on success, and returns-1with an exceptionset on failure.If this is not called in the main thread of the maininterpreter, this function does nothing and returns
0.The caller must hold anattached thread state.Added in version 3.1.
Changed in version 3.12:This function only runs pending calls in the main interpreter.
- intPyThreadState_SetAsyncExc(unsignedlongid,PyObject*exc)¶
- Part of theStable ABI.
Asynchronously raise an exception in a thread. Theid argument is the threadid of the target thread;exc is the exception object to be raised. Thisfunction does not steal any references toexc. To prevent naive misuse, youmust write your own C extension to call this. Must be called with anattached thread state.Returns the number of thread states modified; this is normally one, but will bezero if the thread id isn’t found. Ifexc is
NULL, the pendingexception (if any) for the thread is cleared. This raises no exceptions.Changed in version 3.7:The type of theid parameter changed fromlong tounsignedlong.
Operating system thread APIs¶
- PYTHREAD_INVALID_THREAD_ID¶
Sentinel value for an invalid thread ID.
This is currently equivalent to
(unsignedlong)-1.
- unsignedlongPyThread_start_new_thread(void(*func)(void*),void*arg)¶
- Part of theStable ABI.
Start functionfunc in a new thread with argumentarg.The resulting thread is not intended to be joined.
func must not be
NULL, butarg may beNULL.On success, this function returns the identifier of the new thread; on failure,this returns
PYTHREAD_INVALID_THREAD_ID.The caller does not need to hold anattached thread state.
- unsignedlongPyThread_get_thread_ident(void)¶
- Part of theStable ABI.
Return the identifier of the current thread, which will never be zero.
This function cannot fail, and the caller does not need to hold anattached thread state.
See also
- PyObject*PyThread_GetInfo(void)¶
- Part of theStable ABI since version 3.3.
Get general information about the current thread in the form of astruct sequence object. This information isaccessible as
sys.thread_infoin Python.On success, this returns a newstrong reference to the threadinformation; on failure, this returns
NULLwith an exception set.The caller must hold anattached thread state.
- PY_HAVE_THREAD_NATIVE_ID¶
This macro is defined when the system supports native thread IDs.
- unsignedlongPyThread_get_thread_native_id(void)¶
- Part of theStable ABI on platforms with native thread IDs.
Get the native identifier of the current thread as it was assigned by the operatingsystem’s kernel, which will never be less than zero.
This function is only available when
PY_HAVE_THREAD_NATIVE_IDisdefined.This function cannot fail, and the caller does not need to hold anattached thread state.
See also
- voidPyThread_exit_thread(void)¶
- Part of theStable ABI.
Terminate the current thread. This function is generally considered unsafeand should be avoided. It is kept solely for backwards compatibility.
This function is only safe to call if all functions in the full callstack are written to safely allow it.
Warning
If the current system uses POSIX threads (also known as “pthreads”),this callspthread_exit(3), which attempts to unwind the stackand call C++ destructors on some libc implementations. However, if a
noexceptfunction is reached, it may terminate the process.Other systems, such as macOS, do unwinding.On Windows, this function calls
_endthreadex(), which kills the threadwithout calling C++ destructors.In any case, there is a risk of corruption on the thread’s stack.
Deprecated since version 3.14.
- voidPyThread_init_thread(void)¶
- Part of theStable ABI.
Initialize
PyThread*APIs. Python executes this function automatically,so there’s little need to call it from an extension module.
- intPyThread_set_stacksize(size_tsize)¶
- Part of theStable ABI.
Set the stack size of the current thread tosize bytes.
This function returns
0on success,-1ifsize is invalid, or-2if the system does not support changing the stack size. This functiondoes not set exceptions.The caller does not need to hold anattached thread state.
- size_tPyThread_get_stacksize(void)¶
- Part of theStable ABI.
Return the stack size of the current thread in bytes, or
0if the system’sdefault stack size is in use.The caller does not need to hold anattached thread state.