Skip to content

Commit fecc4f2

Browse files
authored
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
1 parent a712679 commit fecc4f2

File tree

3 files changed

+42
-29
lines changed

3 files changed

+42
-29
lines changed

Include/cpython/unicodeobject.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,6 @@ PyAPI_FUNC(int) _PyUnicode_FormatAdvancedWriter(
722722
Py_ssize_t start,
723723
Py_ssize_t end);
724724

725-
PyAPI_FUNC(void) _Py_ReleaseInternedUnicodeStrings(void);
726-
727725
/* --- wchar_t support for platforms which support it --------------------- */
728726

729727
#ifdef HAVE_WCHAR_H

Modules/main.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -839,18 +839,6 @@ pymain_free(void)
839839
_PyPathConfig_ClearGlobal();
840840
_Py_ClearStandardStreamEncoding();
841841
_Py_ClearArgcArgv();
842-
#ifdef __INSURE__
843-
/* Insure++ is a memory analysis tool that aids in discovering
844-
* memory leaks and other memory problems. On Python exit, the
845-
* interned string dictionaries are flagged as being in use at exit
846-
* (which it is). Under normal circumstances, this is fine because
847-
* the memory will be automatically reclaimed by the system. Under
848-
* memory debugging, it's a huge source of useless noise, so we
849-
* trade off slower shutdown for less distraction in the memory
850-
* reports. -baw
851-
*/
852-
_Py_ReleaseInternedUnicodeStrings();
853-
#endif /* __INSURE__ */
854842
}
855843

856844

Objects/unicodeobject.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5151
#include <windows.h>
5252
#endif
5353

54+
/* 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]
5560
class str "PyObject *" "&PyUnicode_Type"
5661
[clinic start generated code]*/
@@ -15157,18 +15162,6 @@ PyUnicode_ClearFreeList(void)
1515715162
return 0;
1515815163
}
1515915164

15160-
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-
}
1517215165

1517315166
void
1517415167
PyUnicode_InternInPlace(PyObject **p)
@@ -15233,8 +15226,10 @@ PyUnicode_InternFromString(const char *cp)
1523315226
return s;
1523415227
}
1523515228

15236-
void
15237-
_Py_ReleaseInternedUnicodeStrings(void)
15229+
15230+
#if defined(WITH_VALGRIND) || defined(__INSURE__)
15231+
static void
15232+
unicode_release_interned(void)
1523815233
{
1523915234
PyObject *keys;
1524015235
PyObject *s;
@@ -15249,14 +15244,16 @@ _Py_ReleaseInternedUnicodeStrings(void)
1524915244
return;
1525015245
}
1525115246

15252-
/* 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. */
1525615251

1525715252
n = PyList_GET_SIZE(keys);
15253+
#ifdef INTERNED_STATS
1525815254
fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",
1525915255
n);
15256+
#endif
1526015257
for (i = 0; i < n; i++) {
1526115258
s = PyList_GET_ITEM(keys, i);
1526215259
if (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
1528215280
fprintf(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
1528515284
Py_DECREF(keys);
1528615285
PyDict_Clear(interned);
1528715286
Py_CLEAR(interned);
1528815287
}
15288+
#endif
1528915289

1529015290

1529115291
/********************* Unicode Iterator **************************/
@@ -15564,6 +15564,33 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode)
1556415564
return copy;
1556515565
}
1556615566

15567+
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

0 commit comments

Comments
 (0)