diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-06-08 19:27:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-08 19:27:44 (GMT) |
commit | 2ad2bd8b14505ee92600e7988379cfac63086dab (patch) | |
tree | a748f316ac0de4688a5f18e19073bb4917ffb3fe /Python/pylifecycle.c | |
parent | 8698fa83f6c226d35af0367e40dd4387fcccbe40 (diff) | |
download | cpython-2ad2bd8b14505ee92600e7988379cfac63086dab.zip cpython-2ad2bd8b14505ee92600e7988379cfac63086dab.tar.gz cpython-2ad2bd8b14505ee92600e7988379cfac63086dab.tar.bz2 |
[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 7799c8e678f759c7787785c6287140abe641d1b9)
Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8b84644..95b39f4 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -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); |