mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
[3.12] gh-100227: Lock Around Use of the Global "atexit" State (gh-105514) (gh-105517)
The risk of a race with this state is relatively low, but we play it safe anyway.
(cherry picked from commit 7799c8e678
)
Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
This commit is contained in:
parent
8698fa83f6
commit
2ad2bd8b14
4 changed files with 488 additions and 457 deletions
|
@ -2974,24 +2974,35 @@ wait_for_thread_shutdown(PyThreadState *tstate)
|
|||
|
||||
int Py_AtExit(void (*func)(void))
|
||||
{
|
||||
if (_PyRuntime.atexit.ncallbacks >= NEXITFUNCS)
|
||||
struct _atexit_runtime_state *state = &_PyRuntime.atexit;
|
||||
PyThread_acquire_lock(state->mutex, WAIT_LOCK);
|
||||
if (state->ncallbacks >= NEXITFUNCS) {
|
||||
PyThread_release_lock(state->mutex);
|
||||
return -1;
|
||||
_PyRuntime.atexit.callbacks[_PyRuntime.atexit.ncallbacks++] = func;
|
||||
}
|
||||
state->callbacks[state->ncallbacks++] = func;
|
||||
PyThread_release_lock(state->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
call_ll_exitfuncs(_PyRuntimeState *runtime)
|
||||
{
|
||||
atexit_callbackfunc exitfunc;
|
||||
struct _atexit_runtime_state *state = &runtime->atexit;
|
||||
|
||||
PyThread_acquire_lock(state->mutex, WAIT_LOCK);
|
||||
while (state->ncallbacks > 0) {
|
||||
/* pop last function from the list */
|
||||
state->ncallbacks--;
|
||||
atexit_callbackfunc exitfunc = state->callbacks[state->ncallbacks];
|
||||
exitfunc = state->callbacks[state->ncallbacks];
|
||||
state->callbacks[state->ncallbacks] = NULL;
|
||||
|
||||
PyThread_release_lock(state->mutex);
|
||||
exitfunc();
|
||||
PyThread_acquire_lock(state->mutex, WAIT_LOCK);
|
||||
}
|
||||
PyThread_release_lock(state->mutex);
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue