[PyQt] sip: Accessing members results in incorrect/missing data
Phil Thompson
phil at riverbankcomputing.com
Fri Jan 24 11:49:10 GMT 2020
On 24/01/2020 11:03, MatthijsBurgh wrote:
> Phil Thompson-5 wrote
>> On 22/01/2020 21:50, MatthijsBurgh wrote:
>>> Phil Thompson-5 wrote
>>>> On 22/01/2020 13:57, MatthijsBurgh wrote:
>>>>> The first changeset already fixed the issue.
>>>>>
>>>>> The newer changeset creates the situation as desribed in
>>>>> http://python.6.x6.nabble.com/sip-Accessing-members-results-in-incorrect-missing-data-tp5266521p5266740.html,
>>>>> it looks like the release function isn't called anymore. I thought
>>>>> Python GC
>>>>> was able to break up circular references, but it looks like it
>>>>> isn't
>>>>> happening.
>>>>>
>>>>> By running the following code:
>>>>> ```
>>>>> v = Vector(1,2,3)
>>>>> R = Rotation()
>>>>> F = Frame(R,v)
>>>>> v2 = F.p
>>>>> v3 = Frame(F).p
>>>>> v3 = Vector(2,3,4)
>>>>> ```
>>>>> The `release_Frame` is called(print shows up) after the second `v3`
>>>>> assignment when using your first changeset, but the print doesn't
>>>>> show
>>>>> up
>>>>> with your second changeset, today's one.
>>>>>
>>>>> So to me it looks like this will cause a memory leak.
>>>>
>>>> In my own test cases the cycle is broken. Have you run gc.collect()?
>>>> If
>>>> you print out the reference counts to they look correct?
>>>>
>>>>> Side note: I would prefer the usage of a specific key for the
>>>>> member
>>>>> reference to the containing class.
>>>>> I don't think using the same key for both references will cause a
>>>>> problem
>>>>> with overwriting. As a class can't contain a member of the same
>>>>> type,
>>>>> only a
>>>>> member as a pointer to the same type. In which case, the reference
>>>>> isn't
>>>>> kept, if I understand the code correct.
>>>>
>>>> There can be a problem (now fixed) if the type of the variable is
>>>> defined in a different module from the type of the container.
>>>>
>>>> Phil
>>>> _______________________________________________
>>>> PyQt mailing list
>>>
>>>> PyQt@
>>>
>>>> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>>>
>>> In your last changeset (but also the second one), the new frame keeps
>>> alive.
>>> Even after `v3` is assigned a new value. Therefore the unassigned
>>> Frame,
>>> from which only `p` was accessed, stays alive till the end of the
>>> Python
>>> session.
>>>
>>> This happens because `Frame` has a ref to `p`, because of the caching
>>> of the
>>> python object. And `p` has a reference to `Frame`, to keep the class
>>> alive,
>>> to be able to access the member `p`.
>>>
>>> I don't see an easy solution for this at the moment. Do you?
>>
>> As I said, I don't seem to see the problem. The caching is needed as
>> explained in the comments. Did you try gc.collect()?
>>
>> Phil
>> _______________________________________________
>> PyQt mailing list
>
>> PyQt@
>
>> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>
> In a manual test. the GC did not collect the items directly, just at
> the end
> of the session. But if run in a loop, the GC does it job and the memory
> stays about constant.
Yes, the GC isn't invoked as soon as a reference count reaches 0.
> I have found another problem(incl. fix). While running the following
> code:
> ```
> import PyKDL as kdl
> import sip
>
> F = kdl.Frame(
> kdl.Rotation.Quaternion(0, 1, 0, 0),
> kdl.Vector(1, 2, 3))
>
> while True:
> v = F.p
> ```
>
> This will cause a memory leak as shown in the image below.
> <http://python.6.x6.nabble.com/file/t383425/mem_leak.png>
>
> The problem is caused in `sip_api_get_reference` in `siplib.c`.
> PyInt_FromLong(2.7) and PyLong_FromLong(3) return a new reference, see
> https://docs.python.org/2.7/c-api/int.html#c.PyInt_FromLong. Therefore
> a
> `Py_DECREF(key_obj);` needs to be added before returning the object.
>
> The first part of the memory graph show the test with the fix, the peek
> is
> the test without the fix.
Applied, thanks.
> After implementing this fix, could you also release the newest 4.19.X
> version to ubuntu 16.04 & 18.04(and maybe some other distributions as
> well)?
I will make a new release when Qt v5.14.1 is released. I have no control
over what versions are used by Linux distros.
Phil
More information about the PyQt
mailing list