roycornelissen/GMImagePicker.Xamarin

Crash when a user makes a screenshot after picking an image

Closed this issue · 6 comments

NullReferenceException crash in at GMImagePickerController.FinishPickingAssets happens in NuGet package 2.1.0 when a user after picking an image decides to take a screenshot of the app.

Happens on iOS 11, any real device.

{System.NullReferenceException: Object reference not set to an instance of an object at GMImagePicker.GMImagePickerController.FinishPickingAssets (System.Object sender, System.EventArgs args) [0x00028] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/G…}

Detailed stack:

{System.NullReferenceException: Object reference not set to an instance of an object
  at GMImagePicker.GMImagePickerController.FinishPickingAssets (System.Object sender, System.EventArgs args) [0x00028] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMImagePickerController.cs:369 
  at GMImagePicker.GMImagePickerController.SelectAsset (Photos.PHAsset asset) [0x000d7] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMImagePickerController.cs:331 
  at GMImagePicker.GMGridViewController+GMGridViewCollectionViewSource.ItemSelected (UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) [0x0001c] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMGridViewController.cs:549 
  at GMImagePicker.GMGridViewController+<>c__DisplayClass28_2.<PhotoLibraryDidChange>b__1 () [0x00102] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMGridViewController.cs:383 
  at ObjCRuntime.Trampolines+SDAction.Invoke (System.IntPtr block) [0x00016] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/ObjCRuntime/Trampolines.g.cs:12074 
  at (wrapper native-to-managed) ObjCRuntime.Trampolines+SDAction.Invoke(intptr)}

image

Hey @alexsorokoletov, sorry for my absence, it's been crazy busy at work lately...

I'm having trouble reproducing this problem, can you verify your settings? I have a hunch that this has something to do with automatic selection of camera images (as soon as a new image is added to the camera roll, it is auto-selected if you set the AutoSelectCameraImages property to true) in combination with AllowsMultipleSelection = false, is that the case?

I think the bug might be that it still tries to auto select the new image while the controller is being dismissed, and it tries to automatically dismiss again...

Can you share your settings and repro steps? When does the user take the screenshot? After clicking Finished or just before?

@roycornelissen no problem, thank you for the package.
User takes screenshot after picking up something from the gallery.
Indeed, we have AllowsMultipleSelection = false and AutoSelectCameraImages = true.

Your guess is probably right, let me check if disabling AutoSelectCameraImages will help.

Here is a sample that reproduces the problem. Based on an empty Xamarin Master-Detail app.
PickerCrashRepro.zip

Run the app on a device, hit "+" button to add any item and tap the item to get to the detail view.
Then hit the button and pick an image. Once you return from the picker, take a screenshot and wait till the screenshot thumbnail disappears. App will crash with this stacktrace:

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
  at GMImagePicker.GMImagePickerController.FinishPickingAssets (System.Object sender, System.EventArgs args) [0x00028] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMImagePickerController.cs:369 
  at GMImagePicker.GMImagePickerController.SelectAsset (Photos.PHAsset asset) [0x000d7] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMImagePickerController.cs:331 
  at GMImagePicker.GMGridViewController+GMGridViewCollectionViewSource.ItemSelected (UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) [0x0001c] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMGridViewController.cs:549 
  at GMImagePicker.GMGridViewController+<>c__DisplayClass28_2.<PhotoLibraryDidChange>b__1 () [0x00102] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMGridViewController.cs:383 
  at ObjCRuntime.Trampolines+SDAction.Invoke (System.IntPtr block) [0x00016] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/ObjCRuntime/Trampolines.g.cs:12074 
  at (wrapper native-to-managed) ObjCRuntime.Trampolines+SDAction.Invoke(intptr)
--- End of stack trace from previous location where exception was thrown ---
  at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSend_IntPtr_IntPtr(intptr,intptr,intptr,intptr)
  at UIKit.UICollectionView.PerformBatchUpdates (System.Action updates, UIKit.UICompletionHandler completed) [0x0005c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/UIKit/UICollectionView.g.cs:551 
  at GMImagePicker.GMGridViewController+<>c__DisplayClass28_0.<PhotoLibraryDidChange>b__0 () [0x000a7] in /Users/roy/Projects/GitHub/GMImagePicker.Xamarin/src/GMImagePicker/GMGridViewController.cs:372 
  at CoreFoundation.DispatchQueue.static_dispatcher_to_managed (System.IntPtr context) [0x00038] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/CoreFoundation/Dispatch.cs:344 
  at (wrapper native-to-managed) CoreFoundation.DispatchQueue.static_dispatcher_to_managed(intptr)
--- End of stack trace from previous location where exception was thrown ---
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/UIKit/UIApplication.cs:79 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0002c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.10.1.178/src/Xamarin.iOS/UIKit/UIApplication.cs:63 
  at PickerCrashRepro.Application.Main (System.String[] args) [0x00001] in /Users/alex/Projects/PickerCrashRepro/PickerCrashRepro/Main.cs:12 

Hi @alexsorokoletov thanks for the repo, it helped me diagnose the issue. I've just pushed a fix and Nuget version 2.2.2 should arrive soon in the feeds.

This was actually quite a nasty bug. The problem was that one of the view controllers (GMGridViewController) was left around as a listener to changes to the photo album. It's doing this so it can update the view when a new image is added through the camera. But of course a screen shot is also added to the collection, so the Observer was still notified and it tried to perform the regular logic (by selecting the image and notifying the GMImagePicker of the selection, but of course the picker was already dismissed and gone, hence the NullReferenceException).

So it was also a memory leak of some sort. I've added some cleanup logic to prevent this.

Thank you @roycornelissen! We've updated the package and the crash is gone.
👍