-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Py_Finalize() doesn't clear all Python objects at exit #44470
Comments
This C code: #include <Python.h>
int main(int argc, char *argv[])
{
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
Py_Initialize(); Py_Finalize();
} Produces this output: A similar program configured to call the Py_Initialize()/Py_Finalize() 1000 times ends up with: This is with a fresh debug build of Python 2.5.0 on Windows XP, using Visual C++ 2003. |
Does the title of this issue accurately reflect the current status of the Python interpreter? |
Yes, some objects are not cleaned in finalization. |
Yes, here is the running result on current 3.3 latest code: This seems to be a known bug that Py_Finalize() doesn't free all objects according doc http://docs.python.org/dev/c-api/init.html?highlight=py_finalize#Py_Finalize |
Interestingly enough, some of the leaked memory came from the finalize routine itself! Here's one example: 0:004> !heap -p -a 0x000000DB144346F0 |
I tested on the master branch of Python: #include <Python.h>
void func()
{
Py_Initialize(); Py_Finalize();
Py_ssize_t cnt = _Py_GetRefTotal();
printf("sys.gettotalrefcount(): %zd\n", cnt);
}
int main(int argc, char *argv[])
{
Py_SetProgramName(L"./_testembed");
for (int i=0; i < 10; i++) {
func();
}
} Each iteration leaks around 5,000 Python objects: |
I marked bpo-6741 as a duplicate of this issue. |
I marked bpo-26888 as a duplicate of this issue. |
I marked bpo-21387 as a duplicate of this issue. |
One part of this issue is that all C extensions of the stdlib should be updated to implement the PEP-489 "Multi-phase extension module initialization". |
I marked bpo-32026 as a duplicate of this issue. |
One part of this issue is that all C extensions of the stdlib should be updated to implement the PEP-489 "Multi-phase extension module initialization".
|
Compare to _Py_ForgetReference(), _Py_INC_REFTOTAL in _Py_NewReference() looks redundant. REF: https://github.com/python/cpython/blob/master/Include/object.h#L442 master brach baseline in my vm:
after PR17883
|
FWIW, i counted the difference of each file's refs after [('Objects/dictobject.c', 21434), ('Python/marshal.c', 8135), ('Objects/codeobject.c', 6245), ('Objects/listobject.c', 6037), ('Objects/tupleobject.c', 4169), ('Objects/boolobject.c', 2433), ('Objects/object.c', 2364), ('Objects/unicodeobject.c', 1541), ('Objects/longobject.c', 1387), ('Objects/funcobject.c', 528), ('Objects/classobject.c', 528), ('Objects/abstract.c', 463), ('Python/structmember.c', 369), ('./Include/objimpl.h', 277), ('Objects/stringlib/partition.h', 273), ('Python/import.c', 259), ('Python/codecs.c', 197), ('./Modules/signalmodule.c', 61), ('./Modules/_threadmodule.c', 59), ('Objects/exceptions.c', 15), ('Objects/bytesobject.c', 5), ('./Modules/_weakref.c', 4), ('Python/_warnings.c', 3), ('./Modules/timemodule.c', 1), ('./Modules/_codecsmodule.c', 1), ('Objects/bytearrayobject.c', 1), ('Python/compile.c', 1), ('Objects/sliceobject.c', 0), ('Objects/memoryobject.c', 0), ('Python/context.c', -1), ('Objects/clinic/longobject.c.h', -1), ('Objects/enumobject.c', -1), ('Modules/gcmodule.c', -1), ('Objects/namespaceobject.c', -1), ('Objects/stringlib/unicode_format.h', -2), ('Objects/rangeobject.c', -3), ('Python/pystate.c', -4), ('Objects/fileobject.c', -14), ('./Modules/_io/clinic/bufferedio.c.h', -17), ('./Modules/_io/iobase.c', -21), ('Python/modsupport.c', -28), ('./Modules/_io/fileio.c', -28), ('Python/pylifecycle.c', -37), ('./Modules/_io/textio.c', -39), ('Objects/genobject.c', -53), ('Objects/weakrefobject.c', -54), ('./Modules/_io/bufferedio.c', -56), ('./Python/sysmodule.c', -68), ('./Modules/_io/_iomodule.c', -82), ('Python/errors.c', -90), ('Objects/descrobject.c', -110), ('Objects/structseq.c', -113), ('Python/bltinmodule.c', -118), ('Objects/setobject.c', -339), ('Objects/moduleobject.c', -454), ('./Modules/posixmodule.c', -614), ('./Modules/_abc.c', -664), ('Objects/call.c', -755), ('Objects/typeobject.c', -2035), ('Objects/frameobject.c', -6538), ('Python/ceval.c', -7857), ('./Include/object.h', -48292)] |
New changeset ed154c3 by Victor Stinner (Hai Shi) in branch 'master': |
i thinkt that not checking
|
update the above info:
|
|
New changeset 1ea45ae by Hai Shi in branch 'master': |
Leave a note for myself: So far, I don't know which file and fileno create those object. MAYBE I need find a hack way to sign this mallocing operation?(not sure) |
New changeset b2b6e27 by Hai Shi in branch 'master': |
New changeset 7d79568 by Hai Shi in branch 'master': |
Using "./python -IsS" command, sys.modules now only has 3 extensions which are not created by PyModuleDef_Init():
The builtins and sys extensions use many static types. Converting these static types to heap types is blocked by bpo-40601. Soon, bpo-46417 will clear these types. Py_Finalize() does its best to clear explicitly builtins and sys namespaces. |
In bpo-46417, I pushed a change to call _PyDebug_PrintTotalRefs() after destroying the interpreter. I backported locally this change to other Python versions to compare the progress on old Python versions: ./python -I -X showrefcount -c pass command:
Yeah, main is way better than Python 3.10! I pushed many changes in |
My work on bpo-46417 reduces the number of leak references from around 10k to ... minus 4 references :-) Clearing static types and a few "static" objects helped a lot!
At commit a1444f4, I get: $ ./python -I -X showrefcount -c pass
[-4 refs, 61 blocks] I have to investigate why it's negative. It may be caused by bpo-46449 issue. |
Thanks to recent enhancements, epecially in bpo-46417, the last memory blocks are now released at Python exit! The initial issue has been fixed!!! This bug was 15 years old! Current main branch: $ ./python -I -X showrefcount -c pass
[-5 refs, 0 blocks] "0 blocks" means that Python no longer leaks memory at exit. You can use Valgrind to check it ;-) The negative reference count is being discussed in bpo-46449. I close this issue since it has an insane history: too many pull requests, changes, etc. While the work is not 100% done (we need to convert remaining static types to heap types, and convert extensions to multi-phase init), I prefer to address remaining issues in (existing or new) separated issues. See for example the bpo-40077: "Convert static types to heap types: use PyType_FromSpec()". I would like to thank everybody who helped to fix this issue! It's hard to list all names since this issue is a meta issues made of many sub-issues which also have sub-issues. Authors of PEP-573 and PEP-630 also helped fixing this issue! |
I marked bpo-35774 as a duplicate of this issue. |
The negative refcount issue has been fixed ;-) At commit 9a24127, Python now leaks exactly 0 reference count and 0 memory block at exit: $ ./python -I -X showrefcount -c pass
[0 refs, 0 blocks] |
New changeset c9c178f by Victor Stinner in branch 'main': |
New changeset 4657bf7 by Victor Stinner in branch 'main': |
I have teste Python 3.11 "3.11.0rc1 (main, Aug 8 2022, 11:30:54) [MSC v.1932 64 bit (AMD64)]" in Win10 64 bits and it leaks around 2Mb each time you call |
This issue is closed, please open a new issue. |
Ah, it seems like it has been reported as a new issue: #96853 |
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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: