Bug 44935

Summary: pycairo 1.10.0 doesn't implement create_for_data in python3
Product: pycairo Reporter: Rafał Mużyło <galtgendo>
Component: generalAssignee: Steve Chaplin <d74n5pohf9>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: medium CC: paul
Version: unspecified   
Hardware: All   
OS: All   
URL: http://lists.cairographics.org/archives/cairo/2011-December/022563.html
Whiteboard:
i915 platform: i915 features:

Description Rafał Mużyło 2012-01-19 03:44:20 UTC
Not really my bug, but given the questions on the mailing list, should have a bugzilla entry.

Patch sent to the mailing list in December 2011 does seem to work, though somebody should test if it doesn't leak.
Comment 1 Paul Colomiets 2012-03-12 13:42:43 UTC
Fixed memory leaks in this repo:

https://github.com/tailhook/pycairo
Comment 2 Steve Chaplin 2012-04-21 06:51:19 UTC
Implemented ImageSurface.get_data() - it now returns a memoryview.
Comment 3 Steve Chaplin 2012-04-22 03:14:17 UTC
Paul,
I tried your code - it causes pycairo to crash.

$ cd test
$ py.test
gives:
"api_test.py ....Aborted (core dumped)"
the problem is in the function 'test_surface'.

I notice you changed PycairoSurface_FromSurface (sfc, obj)
to PycairoSurface_FromSurface (sfc), and wondered why.

'Obj' is passed into PycairoSurface_FromSurface so it can be referenced to keep it alive while the surface is using it.
If it is garbage collected before the cairo surface writes to it then it can cause segmentation faults, which is probably what is happening here. I added all that code to fix segmentation fault bugs like this.

It's difficult when one Python object uses another object.
If you don't keep the 'paired' objects alive long enough you get segmentation faults.
If you keep them alive too long, you get memory leaks.
You need to keep them alive just long enough to avoid all possible use of garbage collected objects.
Comment 4 Paul Colomiets 2012-04-22 06:01:53 UTC
Well, I don't remember details. But I was pretty sure it's unneeded. It's definitely better to keep Py_buffer alive for ImageSurface, instead of just obj. 

My mistake is probably because the obj is also passed as the `closure` argument for surfaces. However, there is no way to fetch it from the surface. (My current usage of pycairo is for ImageSurface only, so I haven't noticed it).

Would you like me to fix it?
Comment 5 Steve Chaplin 2012-04-22 21:41:21 UTC
I plan to try to get the create_for_data function working this week.
If you want to look at fixing it that would be good, but it must pass the memory leak tests and the other pycairo tests too. If the 'obj' is not needed it would be good to get rid of it, but some method to keep alive python objects used by a cairo.Surface is needed.

In code like this
f = tempfile.TemporaryFile(mode='w+b')
s = cairo.PSSurface(f, 100, 100)

The cairo surface uses the file object 'f'. So we must make sure that 'f' is not garbage collected until we have finished using surface 's'.

f = tempfile.TemporaryFile(mode='w+b')
del f  # try to delete f. f must stay alive until s has finished using it
s = cairo.PSSurface(f, 100, 100)

I'll update test/api_test.py to test this situation properly.
Comment 6 Paul Colomiets 2012-04-23 12:59:39 UTC
Hi Steve,

I've updated the code. It's on master branch at my repository. It passes unit tests as well memory leak tests.

You may want to remove unnecessary test scripts, if you want.
Comment 7 Steve Chaplin 2012-05-05 04:20:21 UTC
Paul, the code was still not correct for image_surface_create_from_png since it used PycairoSurface_FromSurface which is no longer appropriate for PycairoImageSurface which has lost the 'base' field and gained the 'buffer' field.

Implemented create_for_data function.
Changed definition of PycairoSurface to add Py_buffer and keep all surfaces the same, which makes it easier since they can all still use the PycairoSurface_FromSurface function.
Comment 8 Paul Colomiets 2012-05-05 05:01:39 UTC
Thanks Steve!

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.