bpo-36356: Release Unicode interned strings on Valgrind (#12431) · python/cpython@fecc4f2
@@ -51,6 +51,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5151#include <windows.h>
5252#endif
535354+/* Uncomment to display statistics on interned strings at exit when
55+ using Valgrind or Insecure++. */
56+/* #define INTERNED_STATS 1 */
57+58+5459/*[clinic input]
5560class str "PyObject *" "&PyUnicode_Type"
5661[clinic start generated code]*/
@@ -15157,18 +15162,6 @@ PyUnicode_ClearFreeList(void)
1515715162return 0;
1515815163}
151591516415160-void
15161-_PyUnicode_Fini(void)
15162-{
15163-int i;
15164-15165-Py_CLEAR(unicode_empty);
15166-15167-for (i = 0; i < 256; i++)
15168-Py_CLEAR(unicode_latin1[i]);
15169-_PyUnicode_ClearStaticStrings();
15170- (void)PyUnicode_ClearFreeList();
15171-}
15172151651517315166void
1517415167PyUnicode_InternInPlace(PyObject **p)
@@ -15233,8 +15226,10 @@ PyUnicode_InternFromString(const char *cp)
1523315226return s;
1523415227}
152351522815236-void
15237-_Py_ReleaseInternedUnicodeStrings(void)
15229+15230+#if defined(WITH_VALGRIND) || defined(__INSURE__)
15231+static void
15232+unicode_release_interned(void)
1523815233{
1523915234PyObject *keys;
1524015235PyObject *s;
@@ -15249,14 +15244,16 @@ _Py_ReleaseInternedUnicodeStrings(void)
1524915244return;
1525015245 }
152511524615252-/* Since _Py_ReleaseInternedUnicodeStrings() is intended to help a leak
15247+/* Since unicode_release_interned() is intended to help a leak
1525315248 detector, interned unicode strings are not forcibly deallocated;
1525415249 rather, we give them their stolen references back, and then clear
1525515250 and DECREF the interned dict. */
15256152511525715252n = PyList_GET_SIZE(keys);
15253+#ifdef INTERNED_STATS
1525815254fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",
1525915255n);
15256+#endif
1526015257for (i = 0; i < n; i++) {
1526115258s = PyList_GET_ITEM(keys, i);
1526215259if (PyUnicode_READY(s) == -1) {
@@ -15279,13 +15276,16 @@ _Py_ReleaseInternedUnicodeStrings(void)
1527915276 }
1528015277_PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED;
1528115278 }
15279+#ifdef INTERNED_STATS
1528215280fprintf(stderr, "total size of all interned strings: "
1528315281"%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d "
1528415282"mortal/immortal\n", mortal_size, immortal_size);
15283+#endif
1528515284Py_DECREF(keys);
1528615285PyDict_Clear(interned);
1528715286Py_CLEAR(interned);
1528815287}
15288+#endif
152891528915290152901529115291/********************* Unicode Iterator **************************/
@@ -15564,6 +15564,33 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode)
1556415564return copy;
1556515565}
155661556615567+15568+void
15569+_PyUnicode_Fini(void)
15570+{
15571+#if defined(WITH_VALGRIND) || defined(__INSURE__)
15572+/* Insure++ is a memory analysis tool that aids in discovering
15573+ * memory leaks and other memory problems. On Python exit, the
15574+ * interned string dictionaries are flagged as being in use at exit
15575+ * (which it is). Under normal circumstances, this is fine because
15576+ * the memory will be automatically reclaimed by the system. Under
15577+ * memory debugging, it's a huge source of useless noise, so we
15578+ * trade off slower shutdown for less distraction in the memory
15579+ * reports. -baw
15580+ */
15581+unicode_release_interned();
15582+#endif /* __INSURE__ */
15583+15584+Py_CLEAR(unicode_empty);
15585+15586+for (Py_ssize_t i = 0; i < 256; i++) {
15587+Py_CLEAR(unicode_latin1[i]);
15588+ }
15589+_PyUnicode_ClearStaticStrings();
15590+ (void)PyUnicode_ClearFreeList();
15591+}
15592+15593+1556715594/* A _string module, to export formatter_parser and formatter_field_name_split
1556815595 to the string.Formatter class implemented in Python. */
1556915596