classification
Title: Refleak in CDataObject
Type: resource usage Stage: resolved
Components: ctypes Versions: Python 3.8
process
Status: closed Resolution: works for me
Dependencies: Superseder:
Assigned To: Nosy List: FFY00, Joseph Sible, cubinator, zach.ware
Priority: normal Keywords:

Created on 2020-04-28 17:38 by cubinator, last changed 2020-05-21 02:11 by zach.ware. This issue is now closed.

Messages (3)
msg367549 - (view) Author: Cubi (cubinator) Date: 2020-04-28 17:38
String buffers are not freed when pointers to them (created via ctypes.cast) are deleted, even though those pointers hold references to the string buffer (in tagCDataObject.b_objects, I think). Code examples can be found on StackOverflow.com [1]. Thanks to Mark Tolonen's answer on that StackOverflow post we know that it is a refcount problem.

Tested in
  Python v3.7.4 x64 on Windows 10 x64, and in
  Python v3.8.2 x64 on ArchLinux x64 (5.6.7-arch1-1)

[1] https://stackoverflow.com/q/61479041
msg368480 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2020-05-08 22:55
This looks like a simple reference cycle, as far as I can tell; I don't see an actual refleak.  Reproducing using Mark's code from StackOverflow (adjusted):

$ ./python.exe -X showrefcount
Python 3.9.0a6+ (heads/master-dirty:d10091aa17, May  8 2020, 17:43:51) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
[48551 refs, 15489 blocks]
>>> from ctypes import *
[53774 refs, 17227 blocks]
>>> s = create_string_buffer(1<<30);del s
[53832 refs, 17254 blocks]
>>> s = create_string_buffer(1<<30);del s
[53832 refs, 17255 blocks]
>>> s = create_string_buffer(1<<30);del s
[53832 refs, 17254 blocks]
>>> s = create_string_buffer(1<<30);s = cast(s, c_void_p);del s
[53839 refs, 17258 blocks]
>>> s = create_string_buffer(1<<30);s = cast(s, c_void_p);del s
[53844 refs, 17262 blocks]
>>> import gc
[54078 refs, 17315 blocks]
>>> gc.collect()
13
[54030 refs, 17182 blocks]
>>> 
[54030 refs, 17199 blocks]
>>> s = create_string_buffer(1<<30);del s
[54077 refs, 17227 blocks]
>>> gc.collect()
9
[54030 refs, 17182 blocks]
>>> s = create_string_buffer(1<<30);s = cast(s, c_void_p);del s;gc.collect()
11
[54030 refs, 17182 blocks]
>>> s = create_string_buffer(1<<30);s = cast(s, c_void_p);del s;gc.collect()
11
[54030 refs, 17182 blocks]



I'll freely admit that I'm way out of my depth here, but this doesn't look like a bug as far as I can tell.  `ctypes` seems to be creating some cyclic references internally, but a collection clears them right up.
msg369488 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2020-05-21 02:11
Absent anyone showing me where a proper refleak is here, I'm closing the issue.
History
Date User Action Args
2020-05-21 02:11:38zach.waresetstatus: open -> closed
resolution: works for me
messages: + msg369488

stage: resolved
2020-05-08 23:21:53FFY00setnosy: + FFY00
2020-05-08 22:55:36zach.waresetnosy: + zach.ware
messages: + msg368480
2020-04-28 20:58:07Joseph Siblesetnosy: + Joseph Sible
2020-04-28 17:38:18cubinatorcreate