From f56893944a81f0168dd82544d4a8dd0da7102c72 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 04:21:47 +0900 Subject: [PATCH 1/6] fix crash --- Modules/_decimal/_decimal.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 0e743a609d33d6..a67a0b14f8df61 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1419,12 +1419,6 @@ context_dealloc(PyDecContextObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); -#ifndef WITH_DECIMAL_CONTEXTVAR - decimal_state *state = get_module_state_by_def(Py_TYPE(self)); - if (self == state->cached_context) { - state->cached_context = NULL; - } -#endif (void)context_clear(self); tp->tp_free(self); Py_DECREF(tp); @@ -1701,7 +1695,8 @@ current_context_from_dict(decimal_state *modstate) /* Cache the context of the current thread, assuming that it * will be accessed several times before a thread switch. */ - modstate->cached_context = (PyDecContextObject *)tl_context; + Py_XSETREF(modstate->cached_context, + (PyDecContextObject *)Py_NewRef(tl_context)); modstate->cached_context->tstate = tstate; /* Borrowed reference with refcount==1 */ From 9a23672e549bb12237435b75a922b1f6a7da072f Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 04:22:19 +0900 Subject: [PATCH 2/6] fix refleak --- Modules/_decimal/_decimal.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index a67a0b14f8df61..03ea206b6a3d0a 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -6117,6 +6117,16 @@ decimal_traverse(PyObject *module, visitproc visit, void *arg) Py_VISIT(state->Rational); Py_VISIT(state->SignalTuple); + if (state->signal_map != NULL) { + for (DecCondMap *cm = state->signal_map; cm->name != NULL; cm++) { + Py_VISIT(cm->ex); + } + } + if (state->cond_map != NULL) { + for (DecCondMap *cm = state->cond_map + 1; cm->name != NULL; cm++) { + Py_VISIT(cm->ex); + } + } return 0; } From 286a9d258c5772b36869e3cbcadb671ced68710a Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 04:33:36 +0900 Subject: [PATCH 3/6] NEWS --- .../next/Library/2024-09-04-18-23-43.gh-issue-123657.Oks4So.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-09-04-18-23-43.gh-issue-123657.Oks4So.rst diff --git a/Misc/NEWS.d/next/Library/2024-09-04-18-23-43.gh-issue-123657.Oks4So.rst b/Misc/NEWS.d/next/Library/2024-09-04-18-23-43.gh-issue-123657.Oks4So.rst new file mode 100644 index 00000000000000..efebd21e26962a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-04-18-23-43.gh-issue-123657.Oks4So.rst @@ -0,0 +1,2 @@ +Fix crash and memory leak in :func:`decimal.getcontext`. It crashed when using +a thread-local context by ``--with-decimal-contextvar=no``. From 3e5596eb32a161df9f292befc60faf34eb18e366 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:45:47 +0900 Subject: [PATCH 4/6] fix leak in setcontext() --- Modules/_decimal/_decimal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 03ea206b6a3d0a..d2719aa4caa18a 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -76,7 +76,8 @@ typedef struct { #ifndef WITH_DECIMAL_CONTEXTVAR /* Key for thread state dictionary */ PyObject *tls_context_key; - /* Invariant: NULL or the most recently accessed thread local context */ + /* Invariant: NULL or a strong reference to the most recently accessed + thread local context object, not a borrowed reference. */ struct PyDecContextObject *cached_context; #else PyObject *current_context_var; @@ -1764,7 +1765,7 @@ PyDec_SetCurrentContext(PyObject *self, PyObject *v) Py_INCREF(v); } - state->cached_context = NULL; + Py_CLEAR(state->cached_context); if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) { Py_DECREF(v); return NULL; From 82161d46f0f25876a6cff535a04a089cac055d02 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:44:57 +0900 Subject: [PATCH 5/6] more explicit comment --- Modules/_decimal/_decimal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index d2719aa4caa18a..23ea19bbebd0ca 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -77,8 +77,8 @@ typedef struct { /* Key for thread state dictionary */ PyObject *tls_context_key; /* Invariant: NULL or a strong reference to the most recently accessed - thread local context object, not a borrowed reference. */ - struct PyDecContextObject *cached_context; + thread local context. */ + struct PyDecContextObject *cached_context; /* Do not borrow */ #else PyObject *current_context_var; #endif From 6a52179fb0cc1862e8921d2f55b1efe5e65ef430 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:59:11 +0900 Subject: [PATCH 6/6] reword --- Modules/_decimal/_decimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 23ea19bbebd0ca..96212875154cb8 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -78,7 +78,7 @@ typedef struct { PyObject *tls_context_key; /* Invariant: NULL or a strong reference to the most recently accessed thread local context. */ - struct PyDecContextObject *cached_context; /* Do not borrow */ + struct PyDecContextObject *cached_context; /* Not borrowed */ #else PyObject *current_context_var; #endif