-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
platform.win32_ver() leaks in 2.7.12 #72119
Comments
Running; platform.win32_ver() returns; |
Hum, can you please elaborate the issue? What is leaked_objects.txt? |
I did a gc.get_objects() before and after platform.win32_ver() and printed If I run platform.win32_ver() in a loop I see the memory increasing. On 1 September 2016 at 17:35, STINNER Victor <report@bugs.python.org> wrote:
|
New changeset 384c178cf823 by Steve Dower in branch '3.5': New changeset 31b7eaff5588 by Steve Dower in branch 'default': |
I fixed in 3.5 and 3.6, but I'm not set up for 2.7 so someone will have to backport it. |
New changeset dbfcb3b9c3c1 by Steve Dower in branch '3.5': |
Backed out because of bpo-28059. I'll rewrite this to properly use native code. |
The leak is due the pointer-type cache that ctypes.POINTER uses. The type the pointer refers to is used as the key. In this case, VS_FIXEDFILEINFO is created each time win32_ver is called, so the pointer-type cache grows without bound. Example leak: >>> import psutil, platform
>>> proc = psutil.Process()
>>> proc.memory_info().rss
14704640
>>> for i in range(10000):
... v = platform.win32_ver()
...
>>> proc.memory_info().rss
92704768
>>> for i in range(10000):
... v = platform.win32_ver()
...
>>> proc.memory_info().rss
168861696 Clearing the cache followed by a collect() reclaims the leaked memory for the most part: >>> import gc, ctypes
>>> gc.collect()
333
>>> proc.memory_info().rss
168849408
>>> ctypes._pointer_type_cache.clear()
>>> gc.collect()
740000
>>> proc.memory_info().rss
20303872 It's a moot point, since Steve plans to re-implement this check in C, but the minimal change to fix this leak is to bypass the pointer-type cache by manually subclassing ctypes._Pointer: class PVS_FIXEDFILEINFO(_Pointer):
_type_ = VS_FIXEDFILEINFO
pvi = PVS_FIXEDFILEINFO() There's no more leak after this change: >>> import psutil, platform
>>> proc = psutil.Process()
>>> proc.memory_info().rss
15450112
>>> for i in range(10000):
... v = platform.win32_ver()
...
>>> proc.memory_info().rss
16592896
>>> for i in range(10000):
... v = platform.win32_ver()
...
>>> proc.memory_info().rss
16601088 |
Maybe we should also fix ctypes to use an LRU cache like |
Limiting the pointer-type cache could be a problem. It's expected that POINTER() returns a reference to an existing pointer type. ctypes uses Python types to ensure compatible C data types. For example: LP_c_int = ctypes.POINTER(ctypes.c_int)
class LP_c_int_uncached(ctypes._Pointer):
_type_ = ctypes.c_int >>> arr = (LP_c_int * 2)()
>>> ctypes.POINTER(ctypes.c_int) is LP_c_int
True
>>> arr[0] = ctypes.POINTER(ctypes.c_int)()
>>> arr[1] = LP_c_int_uncached()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: incompatible types, LP_c_int_uncached instance
instead of LP_c_int instance The docs could warn users that the cache used by ctypes.POINTER(), and implicitly by ctypes.pointer(), will leak memory if it's called with a type that's created at function scope instead of at module or class-body scope. |
New changeset 9b0d661a16de by Steve Dower in branch '2.7': |
New changeset db4b254f5df4 by Steve Dower in branch '3.5': New changeset 14fca2c8eb36 by Steve Dower in branch '3.6': New changeset 19ceb5034fe5 by Steve Dower in branch 'default': |
Phew. Doing that in a reasonable way for all the active versions was a pain, but I think I managed it. In short:
AFAICT the implementation is solid, but please shout if you spot anything weird/wrong. |
Misc/NEWS
so that it is managed by towncrier #552Note: 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: