Bug 34633 - Segfault in iOS serializing a CGImage to PNG in UIKit.UIImage.AsPNG
Summary: Segfault in iOS serializing a CGImage to PNG in UIKit.UIImage.AsPNG
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 9.4 (iOS 9.2)
Hardware: PC Mac OS
: Normal normal
Target Milestone: C6SR1
Assignee: Rolf Bjarne Kvinge [MSFT]
: 37713 ()
Depends on:
Reported: 2015-10-07 11:14 UTC by Fluendo dev team
Modified: 2016-01-29 10:44 UTC (History)
4 users (show)

Is this bug a regression?: ---
Last known good build:

Stacktrace (11.59 KB, text/plain)
2015-10-07 11:14 UTC, Fluendo dev team

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Fluendo dev team 2015-10-07 11:14:23 UTC
In our application, I am seeing that UIKit.UIImage.AsPNG() returns null for the same CGImage instance after a while. Reading the documentation it seems like the internal data of the CGImage is corrupted/restted somehow[1]:
"This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format."

The CGImage instance in the managed world seems correct, I can retrieve all the properties such as widht, height, colorspace and the refcount returned by CFGetRetainCount of the unmanaged instance returns >0.

Trying to isolate the problem, I came up with a test case [2] that can reproduce the issue, except that this time it ends up with a native stacktrace attached to bug. I have tried to replicate as much as possible our application setup but in our app there is not segfault, UIKit.UIImage.AsPNG return null instead. The bug is triggered when calling the method Serialize in CGImageBug.Image and it can happen at any time.

The same test case works fine on Android.

[1] https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/index.html#//apple_ref/c/func/UIImagePNGRepresentation

[2] https://github.com/fluendo/cgimagebug
Comment 1 Fluendo dev team 2015-10-07 11:14:48 UTC
Created attachment 13223 [details]
Comment 2 Rolf Bjarne Kvinge [MSFT] 2015-10-07 14:15:40 UTC

maccore/master: 988088b5707f1040c9acd51cb5b9004c1ac771d4
Comment 4 Fluendo dev team 2015-10-07 15:21:22 UTC
Awesome! We are just starting with Xamarin in mobile platforms and this is the first bug we have to deal with.
Since it's a pretty critical bug to us because it's affecting our core and it's triggered in many places in our application, I'd like to know if there is a workaround for it, like manually retaining a missing reference somewhere.
macccore seems to be a private project so I can't know how it was fixed and if there is an easy workaround :)
Comment 5 Rolf Bjarne Kvinge [MSFT] 2015-10-08 05:38:33 UTC
The problem is that when you do this (in iOS/Image.cs):

    CGDataProvider dataProvider = new CGDataProvider (ser, 0, ser.Length);
    CGImage img = CGImage.FromPNG (dataProvider, null, false, CGColorRenderingIntent.Default); 

the native CGImage will keep a reference to the native dataProvider object. At some time later, the GC will free the managed dataProvider instance, and we'll (incorrectly) free the 'ser' array with the image data as well, and if the CGImage later flushes the image data and wants to re-read it, it'll read freed memory.

A possible workaround is to make sure the GC doesn't free the dataProvider instance until the CGImage is freed as well: https://gist.github.com/rolfbjarne/ea5787a972e2d50c896d (this will not work if it's possible the managed CGImage can be freed by the GC while the corresponding native object is still alive and expected to render images, since then you'd run into the same problem again).

Another solution (which works all the time, but is slower) is to write the image data to a file, and use CGDataProvider.FromFile to load it again.
Comment 6 Fluendo dev team 2015-10-08 06:02:15 UTC
That's more or less what I was suspecting, thanks for the confirmation and for the workaround!
Comment 7 Rajneesh Kumar 2015-11-23 11:58:12 UTC
Build Info: monotouch-

I have checked this issue with fixed build provided in this trello card. I observed that this issue does not exist with this build. Now I observed that the attached test sample run successfully without any crash.

Screencast: http://www.screencast.com/t/zaPDrNog

This issue has been fixed in master, I will Re-Verify this issue when the fix will merge in release branch.
Comment 8 Rajneesh Kumar 2015-11-24 05:53:11 UTC
Build Info: monotouch-

I have checked this issue with above build and observed that this issue does not exist with this build. Now I observed that the attached test sample run successfully without any crash.

Screencast: http://www.screencast.com/t/RX9fVEwtq

This issue has been fixed I release branch too, hence I am closing this issue.


Environment Info: https://gist.github.com/Rajneesh360Logica/15c8d3fa342d152d527b
Comment 9 Rolf Bjarne Kvinge [MSFT] 2016-01-29 10:44:18 UTC
*** Bug 37713 has been marked as a duplicate of this bug. ***