diff options
author | Victor Stinner <vstinner@python.org> | 2020-07-01 23:19:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-01 23:19:57 (GMT) |
commit | 666ecfb0957a2fa0df5e2bd03804195de74bdfbf (patch) | |
tree | 7d848ed239aeeece4ac47aaec793d1368d531b78 /Objects | |
parent | 90db4653ae37ef90754cfd2cd6ec6857b87a88e6 (diff) | |
download | cpython-666ecfb0957a2fa0df5e2bd03804195de74bdfbf.zip cpython-666ecfb0957a2fa0df5e2bd03804195de74bdfbf.tar.gz cpython-666ecfb0957a2fa0df5e2bd03804195de74bdfbf.tar.bz2 |
bpo-1635741: Release Unicode interned strings at exit (GH-21269)
* PyUnicode_InternInPlace() now ensures that interned strings are
ready.
* Add _PyUnicode_ClearInterned().
* Py_Finalize() now releases Unicode interned strings:
call _PyUnicode_ClearInterned().
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/unicodeobject.c | 60 |
1 files changed, 28 insertions, 32 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index fe46de2..37e7fe5 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -55,8 +55,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <windows.h> #endif -/* Uncomment to display statistics on interned strings at exit when - using Valgrind or Insecure++. */ +/* Uncomment to display statistics on interned strings at exit + in _PyUnicode_ClearInterned(). */ /* #define INTERNED_STATS 1 */ @@ -15681,6 +15681,11 @@ PyUnicode_InternInPlace(PyObject **p) } #ifdef INTERNED_STRINGS + if (PyUnicode_READY(s) == -1) { + PyErr_Clear(); + return; + } + if (interned == NULL) { interned = PyDict_New(); if (interned == NULL) { @@ -15733,23 +15738,29 @@ PyUnicode_InternFromString(const char *cp) } -#if defined(WITH_VALGRIND) || defined(__INSURE__) -static void -unicode_release_interned(void) +void +_PyUnicode_ClearInterned(PyThreadState *tstate) { - if (interned == NULL || !PyDict_Check(interned)) { + if (!_Py_IsMainInterpreter(tstate)) { + // interned dict is shared by all interpreters + return; + } + + if (interned == NULL) { return; } + assert(PyDict_CheckExact(interned)); + PyObject *keys = PyDict_Keys(interned); - if (keys == NULL || !PyList_Check(keys)) { + if (keys == NULL) { PyErr_Clear(); return; } + assert(PyList_CheckExact(keys)); - /* Since unicode_release_interned() is intended to help a leak - detector, interned unicode strings are not forcibly deallocated; - rather, we give them their stolen references back, and then clear - and DECREF the interned dict. */ + /* Interned unicode strings are not forcibly deallocated; rather, we give + them their stolen references back, and then clear and DECREF the + interned dict. */ Py_ssize_t n = PyList_GET_SIZE(keys); #ifdef INTERNED_STATS @@ -15759,9 +15770,8 @@ unicode_release_interned(void) #endif for (Py_ssize_t i = 0; i < n; i++) { PyObject *s = PyList_GET_ITEM(keys, i); - if (PyUnicode_READY(s) == -1) { - Py_UNREACHABLE(); - } + assert(PyUnicode_IS_READY(s)); + switch (PyUnicode_CHECK_INTERNED(s)) { case SSTATE_INTERNED_IMMORTAL: Py_SET_REFCNT(s, Py_REFCNT(s) + 1); @@ -15788,10 +15798,10 @@ unicode_release_interned(void) mortal_size, immortal_size); #endif Py_DECREF(keys); + PyDict_Clear(interned); Py_CLEAR(interned); } -#endif /********************* Unicode Iterator **************************/ @@ -16160,23 +16170,9 @@ _PyUnicode_EnableLegacyWindowsFSEncoding(void) void _PyUnicode_Fini(PyThreadState *tstate) { - struct _Py_unicode_state *state = &tstate->interp->unicode; + // _PyUnicode_ClearInterned() must be called before - int is_main_interp = _Py_IsMainInterpreter(tstate); - if (is_main_interp) { -#if defined(WITH_VALGRIND) || defined(__INSURE__) - /* Insure++ is a memory analysis tool that aids in discovering - * memory leaks and other memory problems. On Python exit, the - * interned string dictionaries are flagged as being in use at exit - * (which it is). Under normal circumstances, this is fine because - * the memory will be automatically reclaimed by the system. Under - * memory debugging, it's a huge source of useless noise, so we - * trade off slower shutdown for less distraction in the memory - * reports. -baw - */ - unicode_release_interned(); -#endif /* __INSURE__ */ - } + struct _Py_unicode_state *state = &tstate->interp->unicode; Py_CLEAR(state->empty_string); @@ -16184,7 +16180,7 @@ _PyUnicode_Fini(PyThreadState *tstate) Py_CLEAR(state->latin1[i]); } - if (is_main_interp) { + if (_Py_IsMainInterpreter(tstate)) { unicode_clear_static_strings(); } |