Commit fecc4f2b authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-36356: Release Unicode interned strings on Valgrind (#12431)

When Python is compiled with Valgrind support, release Unicode
interned strings at exit in _PyUnicode_Fini().

* Rename _Py_ReleaseInternedUnicodeStrings() to
  unicode_release_interned() and make it private.
* unicode_release_interned() is now called from _PyUnicode_Fini():
  it must be called with a running Python thread state for TRASHCAN,
  it cannot be called from pymain_free().
* Don't display statistics on interned strings at exit anymore
parent a712679a
...@@ -722,8 +722,6 @@ PyAPI_FUNC(int) _PyUnicode_FormatAdvancedWriter( ...@@ -722,8 +722,6 @@ PyAPI_FUNC(int) _PyUnicode_FormatAdvancedWriter(
Py_ssize_t start, Py_ssize_t start,
Py_ssize_t end); Py_ssize_t end);
PyAPI_FUNC(void) _Py_ReleaseInternedUnicodeStrings(void);
/* --- wchar_t support for platforms which support it --------------------- */ /* --- wchar_t support for platforms which support it --------------------- */
#ifdef HAVE_WCHAR_H #ifdef HAVE_WCHAR_H
......
...@@ -839,18 +839,6 @@ pymain_free(void) ...@@ -839,18 +839,6 @@ pymain_free(void)
_PyPathConfig_ClearGlobal(); _PyPathConfig_ClearGlobal();
_Py_ClearStandardStreamEncoding(); _Py_ClearStandardStreamEncoding();
_Py_ClearArgcArgv(); _Py_ClearArgcArgv();
#ifdef __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
*/
_Py_ReleaseInternedUnicodeStrings();
#endif /* __INSURE__ */
} }
......
...@@ -51,6 +51,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -51,6 +51,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <windows.h> #include <windows.h>
#endif #endif
/* Uncomment to display statistics on interned strings at exit when
using Valgrind or Insecure++. */
/* #define INTERNED_STATS 1 */
/*[clinic input] /*[clinic input]
class str "PyObject *" "&PyUnicode_Type" class str "PyObject *" "&PyUnicode_Type"
[clinic start generated code]*/ [clinic start generated code]*/
...@@ -15157,18 +15162,6 @@ PyUnicode_ClearFreeList(void) ...@@ -15157,18 +15162,6 @@ PyUnicode_ClearFreeList(void)
return 0; return 0;
} }
void
_PyUnicode_Fini(void)
{
int i;
Py_CLEAR(unicode_empty);
for (i = 0; i < 256; i++)
Py_CLEAR(unicode_latin1[i]);
_PyUnicode_ClearStaticStrings();
(void)PyUnicode_ClearFreeList();
}
void void
PyUnicode_InternInPlace(PyObject **p) PyUnicode_InternInPlace(PyObject **p)
...@@ -15233,8 +15226,10 @@ PyUnicode_InternFromString(const char *cp) ...@@ -15233,8 +15226,10 @@ PyUnicode_InternFromString(const char *cp)
return s; return s;
} }
void
_Py_ReleaseInternedUnicodeStrings(void) #if defined(WITH_VALGRIND) || defined(__INSURE__)
static void
unicode_release_interned(void)
{ {
PyObject *keys; PyObject *keys;
PyObject *s; PyObject *s;
...@@ -15249,14 +15244,16 @@ _Py_ReleaseInternedUnicodeStrings(void) ...@@ -15249,14 +15244,16 @@ _Py_ReleaseInternedUnicodeStrings(void)
return; return;
} }
/* Since _Py_ReleaseInternedUnicodeStrings() is intended to help a leak /* Since unicode_release_interned() is intended to help a leak
detector, interned unicode strings are not forcibly deallocated; detector, interned unicode strings are not forcibly deallocated;
rather, we give them their stolen references back, and then clear rather, we give them their stolen references back, and then clear
and DECREF the interned dict. */ and DECREF the interned dict. */
n = PyList_GET_SIZE(keys); n = PyList_GET_SIZE(keys);
#ifdef INTERNED_STATS
fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n", fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",
n); n);
#endif
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
s = PyList_GET_ITEM(keys, i); s = PyList_GET_ITEM(keys, i);
if (PyUnicode_READY(s) == -1) { if (PyUnicode_READY(s) == -1) {
...@@ -15279,13 +15276,16 @@ _Py_ReleaseInternedUnicodeStrings(void) ...@@ -15279,13 +15276,16 @@ _Py_ReleaseInternedUnicodeStrings(void)
} }
_PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED; _PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED;
} }
#ifdef INTERNED_STATS
fprintf(stderr, "total size of all interned strings: " fprintf(stderr, "total size of all interned strings: "
"%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d " "%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d "
"mortal/immortal\n", mortal_size, immortal_size); "mortal/immortal\n", mortal_size, immortal_size);
#endif
Py_DECREF(keys); Py_DECREF(keys);
PyDict_Clear(interned); PyDict_Clear(interned);
Py_CLEAR(interned); Py_CLEAR(interned);
} }
#endif
/********************* Unicode Iterator **************************/ /********************* Unicode Iterator **************************/
...@@ -15564,6 +15564,33 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode) ...@@ -15564,6 +15564,33 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode)
return copy; return copy;
} }
void
_PyUnicode_Fini(void)
{
#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__ */
Py_CLEAR(unicode_empty);
for (Py_ssize_t i = 0; i < 256; i++) {
Py_CLEAR(unicode_latin1[i]);
}
_PyUnicode_ClearStaticStrings();
(void)PyUnicode_ClearFreeList();
}
/* A _string module, to export formatter_parser and formatter_field_name_split /* A _string module, to export formatter_parser and formatter_field_name_split
to the string.Formatter class implemented in Python. */ to the string.Formatter class implemented in Python. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment