summaryrefslogtreecommitdiffstats
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-06-08 19:27:44 (GMT)
committerGitHub <noreply@github.com>2023-06-08 19:27:44 (GMT)
commit2ad2bd8b14505ee92600e7988379cfac63086dab (patch)
treea748f316ac0de4688a5f18e19073bb4917ffb3fe /Python/pylifecycle.c
parent8698fa83f6c226d35af0367e40dd4387fcccbe40 (diff)
downloadcpython-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.c17
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);