8000 bpo-30860: Fix a refleak. (#3567) · python/cpython@dae0276 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dae0276

Browse files
bpo-30860: Fix a refleak. (#3567)
Resolves bpo-31420. (This was accidentally reverted when in #3565.)
1 parent 93c92f7 commit dae0276

File tree

7 files changed

+47
-43
lines changed

7 files changed

+47
-43
lines changed

Include/object.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,14 +727,13 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
727727
/* Py_REF_DEBUG also controls the display of refcounts and memory block
728728
* allocations at the interactive prompt and at interpreter shutdown
729729
*/
730+
PyAPI_FUNC(PyObject *) _PyDebug_XOptionShowRefCount(void);
730731
PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void);
731-
#define _PY_DEBUG_PRINT_TOTAL_REFS() _PyDebug_PrintTotalRefs()
732732
#else
733733
#define _Py_INC_REFTOTAL
734734
#define _Py_DEC_REFTOTAL
735735
#define _Py_REF_DEBUG_COMMA
736736
#define _Py_CHECK_REFCNT(OP) /* a semicolon */;
737-
#define _PY_DEBUG_PRINT_TOTAL_REFS()
738737
#endif /* Py_REF_DEBUG */
739738

740739
#ifdef COUNT_ALLOCS

Include/pystate.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ typedef struct _is {
6161

6262
/* Used in Python/sysmodule.c. */
6363
int check_interval;
64-
PyObject *warnoptions;
65-
PyObject *xoptions;
6664

6765
/* Used in Modules/_threadmodule.c. */
6866
long num_threads;

Objects/object.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,23 @@ _Py_GetRefTotal(void)
2929
return total;
3030
}
3131

32-
void
33-
_PyDebug_PrintTotalRefs(void) {
34-
PyObject *xoptions, *value;
32+
PyObject *
33+
_PyDebug_XOptionShowRefCount(void)
34+
{
35+
PyObject *xoptions = PySys_GetXOptions();
36+
if (xoptions == NULL)
37+
return NULL;
38+
3539
_Py_IDENTIFIER(showrefcount);
40+
return _PyDict_GetItemId(xoptions, &PyId_showrefcount);
41+
}
3642

37-
xoptions = PySys_GetXOptions();
38-
if (xoptions == NULL)
39-
return;
40-
value = _PyDict_GetItemId(xoptions, &PyId_showrefcount);
41-
if (value == Py_True)
42-
fprintf(stderr,
43-
"[%" PY_FORMAT_SIZE_T "d refs, "
44-
"%" PY_FORMAT_SIZE_T "d blocks]\n",
45-
_Py_GetRefTotal(), _Py_GetAllocatedBlocks());
43+
void
44+
_PyDebug_PrintTotalRefs(void) {
45+
fprintf(stderr,
46+
"[%" PY_FORMAT_SIZE_T "d refs, "
47+
"%" PY_FORMAT_SIZE_T "d blocks]\n",
48+
_Py_GetRefTotal(), _Py_GetAllocatedBlocks());
4649
}
4750
#endif /* Py_REF_DEBUG */
4851

Python/pylifecycle.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,11 @@ Py_FinalizeEx(void)
10111011
while (_PyGC_CollectIfEnabled() > 0)
10121012
/* nothing */;
10131013
#endif
1014+
1015+
#ifdef Py_REF_DEBUG
1016+
PyObject *showrefcount = _PyDebug_XOptionShowRefCount();
1017+
#endif
1018+
10141019
/* Destroy all modules */
10151020
PyImport_Cleanup();
10161021

@@ -1058,7 +1063,10 @@ Py_FinalizeEx(void)
10581063
/* dump hash stats */
10591064
_PyHash_Fini();
10601065

1061-
_PY_DEBUG_PRINT_TOTAL_REFS();
1066+
#ifdef Py_REF_DEBUG
1067+
if (showrefcount == Py_True)
1068+
_PyDebug_PrintTotalRefs();
1069+
#endif
10621070

10631071
#ifdef Py_TRACE_REFS
10641072
/* Display all objects still alive -- this can invoke arbitrary

Python/pystate.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ PyInterpreterState_New(void)
9797
interp->builtins_copy = NULL;
9898
interp->tstate_head = NULL;
9999
interp->check_interval = 100;
100-
interp->warnoptions = NULL;
101-
interp->xoptions = NULL;
102100
interp->num_threads = 0;
103101
interp->pythread_stacksize = 0;
104102
interp->codec_search_path = NULL;

Python/pythonrun.c

Lines changed: 4 additions & 1 deletion
F438
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
113113
err = -1;
114114
for (;;) {
115115
ret = PyRun_InteractiveOneObject(fp, filename, flags);
116-
_PY_DEBUG_PRINT_TOTAL_REFS();
116+
#ifdef Py_REF_DEBUG
117+
if (_PyDebug_XOptionShowRefCount() == Py_True)
118+
_PyDebug_PrintTotalRefs();
119+
#endif
117120
if (ret == E_EOF) {
118121
err = 0;
119122
break;

Python/sysmodule.c

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@ extern const char *PyWin_DLLVersionString;
3636

3737
_Py_IDENTIFIER(_);
3838
_Py_IDENTIFIER(__sizeof__);
39+
_Py_IDENTIFIER(_xoptions);
3940
_Py_IDENTIFIER(buffer);
4041
_Py_IDENTIFIER(builtins);
4142
_Py_IDENTIFIER(encoding);
4243
_Py_IDENTIFIER(path);
4344
_Py_IDENTIFIER(stdout);
4445
_Py_IDENTIFIER(stderr);
46+
_Py_IDENTIFIER(warnoptions);
4547
_Py_IDENTIFIER(write);
4648

4749
PyObject *
@@ -1481,21 +1483,25 @@ list_builtin_module_names(void)
14811483
static PyObject *
14821484
get_warnoptions(void)
14831485
{
1484-
PyObject *warnoptions = PyThreadState_GET()->interp->warnoptions;
1486+
PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
14851487
if (warnoptions == NULL || !PyList_Check(warnoptions)) {
14861488
Py_XDECREF(warnoptions);
14871489
warnoptions = PyList_New(0);
14881490
if (warnoptions == NULL)
14891491
return NULL;
1490-
PyThreadState_GET()->interp->warnoptions = warnoptions;
1492+
if (_PySys_SetObjectId(&PyId_warnoptions, warnoptions)) {
1493+
Py_DECREF(warnoptions);
1494+
return NULL;
1495+
}
1496+
Py_DECREF(warnoptions);
14911497
}
14921498
return warnoptions;
14931499
}
14941500

14951501
void
14961502
PySys_ResetWarnOptions(void)
14971503
{
1498-
PyObject *warnoptions = PyThreadState_GET()->interp->warnoptions;
1504+
PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
14991505
if (warnoptions == NULL || !PyList_Check(warnoptions))
15001506
return;
15011507
PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
@@ -1524,20 +1530,24 @@ PySys_AddWarnOption(const wchar_t *s)
15241530
int
15251531
PySys_HasWarnOptions(void)
15261532
{
1527-
PyObject *warnoptions = PyThreadState_GET()->interp->warnoptions;
1533+
PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
15281534
return (warnoptions != NULL && (PyList_Size(warnoptions) > 0)) ? 1 : 0;
15291535
}
15301536

15311537
static PyObject *
15321538
get_xoptions(void)
15331539
{
1534-
PyObject *xoptions = PyThreadState_GET()->interp->xoptions;
1540+
PyObject *xoptions = _PySys_GetObjectId(&PyId__xoptions);
15351541
if (xoptions == NULL || !PyDict_Check(xoptions)) {
15361542
Py_XDECREF(xoptions);
15371543
xoptions = PyDict_New();
15381544
if (xoptions == NULL)
15391545
return NULL;
1540-
PyThreadState_GET()->interp->xoptions = xoptions;
1546+
if (_PySys_SetObjectId(&PyId__xoptions, xoptions)) {
1547+
Py_DECREF(xoptions);
1548+
return NULL;
1549+
}
1550+
Py_DECREF(xoptions);
15411551
}
15421552
return xoptions;
15431553
}
@@ -2086,16 +2096,6 @@ _PySys_BeginInit(void)
20862096
#undef SET_SYS_FROM_STRING_BORROW
20872097

20882098
/* Updating the sys namespace, returning integer error codes */
2089-
#define SET_SYS_FROM_STRING_BORROW_INT_RESULT(key, value) \
2090-
do { \
2091-
PyObject *v = (value); \
2092-
if (v == NULL) \
2093-
return -1; \
2094-
res = PyDict_SetItemString(sysdict, key, v); \
2095-
if (res < 0) { \
2096-
return res; \
2097-
} \
2098-
} while (0)
20992099
#define SET_SYS_FROM_STRING_INT_RESULT(key, value) \
21002100
do { \
21012101
PyObject *v = (value); \
@@ -2140,23 +2140,18 @@ _PySys_EndInit(PyObject *sysdict)
21402140
SET_SYS_FROM_STRING_INT_RESULT("base_exec_prefix",
21412141
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
21422142

2143-
PyObject *warnoptions = get_warnoptions();
2144-
if (warnoptions == NULL)
2143+
if (get_warnoptions() == NULL)
21452144
return -1;
2146-
SET_SYS_FROM_STRING_BORROW_INT_RESULT("warnoptions", warnoptions);
21472145

2148-
PyObject *xoptions = get_xoptions();
2149-
if (xoptions == NULL)
2146+
if (get_xoptions() == NULL)
21502147
return -1;
2151-
SET_SYS_FROM_STRING_BORROW_INT_RESULT("_xoptions", xoptions);
21522148

21532149
if (PyErr_Occurred())
21542150
return -1;
21552151
return 0;
21562152
}
21572153

21582154
#undef SET_SYS_FROM_STRING_INT_RESULT
2159-
#undef SET_SYS_FROM_STRING_BORROW_INT_RESULT
21602155

21612156
static PyObject *
21622157
makepathobject(const wchar_t *path, wchar_t delim)

0 commit comments

Comments
 (0)
0