summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-07-01 23:19:57 (GMT)
committerGitHub <noreply@github.com>2020-07-01 23:19:57 (GMT)
commit666ecfb0957a2fa0df5e2bd03804195de74bdfbf (patch)
tree7d848ed239aeeece4ac47aaec793d1368d531b78 /Objects
parent90db4653ae37ef90754cfd2cd6ec6857b87a88e6 (diff)
downloadcpython-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.c60
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();
}