You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Python leaks one reference at exit on Windows #91013
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2022-03-03.23:38:23.521>created_at=<Date2022-02-25.16:57:11.797>labels= ['interpreter-core', '3.11']
title='Python leaks one reference at exit on Windows'updated_at=<Date2022-03-22.12:55:03.311>user='https://github.com/vstinner'
As the PyExc_* aliases just deprecated names for PyExc_OSError, there is no need to increment their refcounts. Or they could be decremented in Fini(). Or they could finally be removed entirely.
Oh wow. How did you find this leak? Did you read all C files and check for code specific to Windows? How did you proceed? Well spotted!
Initially, I modified Py_INCREF to dump the object (addr & tp_name) on
initial inc (ob_refcnt == 1) and Py_DECREF to dump on final dec
(ob_refcnt == 0).
Then filter that list (~65K) to find objects not dealloc'ed. Given
those names (~200), cross-check with source files containing 'ifdef
MS_WINDOWS' (and related spellings).
Which command do you type? Do you pass -I option to Python?
Initially, I modified Py_INCREF to dump the object (addr & tp_name) on
initial inc (ob_refcnt == 1) and Py_DECREF to dump on final dec
(ob_refcnt == 0). Then filter that list (~65K) to find objects not
dealloc'ed. Given those names (~200), cross-check with source files
containing 'ifdef MS_WINDOWS' (and related spellings).
That's smart! Thanks for sharing. It may help to identify future leaks.
Even using that change, I still have negative refs (but I still have
Py_TRACE_REFS defined)
Ah, maybe testing with Py_TRACE_REFS shows more bugs. I didn't try Py_TRACE_REFS recently. Well, if someone finds why it's becoming negative, a fix would be welcomed :-)
Did you also modify initconfig.c? That part is required as the usual
processing of the environment variable PYTHONDUMPREFS needed to enable
tracing output is ignored with -I
Activity
vstinner commentedon Feb 25, 2022
"./python -X showrefcount -I -c pass" returns "[0 refs, 0 blocks]" as expected on Linux: Python doesn't leak any reference nor memory block.
But on Windows, it still leaks 1 reference (and 1 memory block)!
vstinner@DESKTOP-DK7VBIL C:\vstinner\python\main>python -X showrefcount -I -c pass
[1 refs, 1 blocks]
I recently added a test in test_embed which now fails on Windows.
See bpo-1635741 "Py_Finalize() doesn't clear all Python objects at exit" for the context.
vstinner commentedon Feb 25, 2022
New changeset ea9612a by Victor Stinner in branch 'main':
bpo-46857: Fix test_embed.test_no_memleak() on Windows (GH-31589)
ea9612a
jkloth commentedon Feb 26, 2022
Good news, the difference on Windows was easy enough to find, bad news total refs are now negative!
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -3647,8 +3647,7 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod)
#define INIT_ALIAS(NAME, TYPE) \ do { \ - Py_INCREF(PyExc_ ## TYPE); \ - Py_XDECREF(PyExc_ ## NAME); \ + Py_XSETREF(PyExc_ ## NAME, PyExc_ ## TYPE); \ PyExc_ ## NAME = PyExc_ ## TYPE; \ if (PyDict_SetItemString(mod_dict, # NAME, PyExc_ ## NAME)) { \ return -1; \As the PyExc_* aliases just deprecated names for PyExc_OSError, there is no need to increment their refcounts. Or they could be decremented in Fini(). Or they could finally be removed entirely.
jkloth commentedon Feb 26, 2022
Note that an allocated block is still leaking.
Strange as well, when using dump_refs, the total refs are much more negative (-12 linux, -13 Windows)
vstinner commentedon Feb 26, 2022
Oh wow. How did you find this leak? Did you read all C files and check for code specific to Windows? How did you proceed? Well spotted!
I proposed #75775 to fix this macro.
Which command do you type? Do you pass -I option to Python?
With my PR, I get exactly 0 on Linux:
Right, with my PR, I now get 1 leaked memory block on Windows:
jeremykloth commentedon Feb 26, 2022
Initially, I modified Py_INCREF to dump the object (addr & tp_name) on
initial inc (ob_refcnt == 1) and Py_DECREF to dump on final dec
(ob_refcnt == 0).
Then filter that list (~65K) to find objects not dealloc'ed. Given
those names (~200), cross-check with source files containing 'ifdef
MS_WINDOWS' (and related spellings).
For linux:
./configure --enabled-shared --with-py-debug --with-trace-refs
make build_all
LD_LIBRARY_PATH=$PWD ./python -X showrefcount -I -c pass
For Windows:
Add "#define Py_TRACE_REFS 1" to PC\pyconfig.h
build.bat -d -e
amd64\python_d.exe -X showrefcount -I -c pass
Even using that change, I still have negative refs (but I still have
Py_TRACE_REFS defined)
jeremykloth commentedon Feb 26, 2022
(that's what I get for typing from memory):
./configure --enable-shared --with-pydebug --with-trace-refs
I initially missed the _PySet_Dummy change, with that total refs (w/o
dump_refs) is now 0.
vstinner commentedon Feb 26, 2022
New changeset ad56919 by Victor Stinner in branch 'main':
bpo-46857: Fix refleak in OSError INIT_ALIAS() (GH-31594)
ad56919
vstinner commentedon Feb 26, 2022
That's smart! Thanks for sharing. It may help to identify future leaks.
Ah, maybe testing with Py_TRACE_REFS shows more bugs. I didn't try Py_TRACE_REFS recently. Well, if someone finds why it's becoming negative, a fix would be welcomed :-)
vstinner commentedon Feb 26, 2022
I just built Python with --with-trace-refs. On Linux, it works as expected:
jeremykloth commentedon Feb 26, 2022
Did you also modify initconfig.c? That part is required as the usual
processing of the environment variable PYTHONDUMPREFS needed to enable
tracing output is ignored with -I
vstinner commentedon Feb 27, 2022
Ah, with PYTHONDUMPREFS=1 (and without -I), I get a negative ref count:
I don't plan to investigate this issue. I'm not using PYTHONDUMPREFS=1 anymore.
vstinner commentedon Mar 3, 2022
The initial issue "Python leaks one reference at exit on Windows" is now fixed.
If someone wants to investigate the remaining leak of 1 memory block or the negative ref count of PYTHONDUMPREFS=1, please open a separated issue.
vstinner commentedon Mar 22, 2022
The last leak of a memory block on Windows was fixed by:
New changeset 88872a2 by Jeremy Kloth in branch 'main':
bpo-47084: Clear Unicode cached representations on finalization (GH-32032)
88872a2