Apache Cordova
  1. Apache Cordova
  2. CB-391

navigator.camera.getPicture() crashing on iOS after memory warning

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.5.0
    • Fix Version/s: 1.7.0
    • Component/s: iOS
    • Labels:
      None
    • Environment:

      2 x iPhone 4S, iOS 5.1. Can't replicate on simulator or iHone 3GS with iOS 5.0.1

      Description

      getPicture has become very unstable on previously working code, affecting both Phonegap 1.4.1 and Cordova 1.5.0. Contributing factors, since last working build I have upgraded Xcode to 4.3.2 (from whatever the last version was) and iPhone to iOS 5.1 from 5.0.1.

      Memory warning is received on displaying camera, app crashes when you select 'use'. Restarting device usually resolves problem for a limited amount of time. Problem is intermittent and sometime difficult to replicate. Selecting from Photo library works fine.

      Options used:

      var options =

      { quality: 40, sourceType: Camera.DestinationType.FILE_URI }

      ;

      See https://groups.google.com/forum/?hl=en?hl%3Den&fromgroups#!topic/phonegap/ZLbw0s4JREs for more details.

      See attached for example crash log.

        Issue Links

          Activity

          Hide
          Richard Kimber added a comment -

          Removing crash log from description.

          Show
          Richard Kimber added a comment - Removing crash log from description.
          Hide
          Richard Kimber added a comment -

          I ran into the same issue and fixed by using the solution suggested by Jonathan Hobson: comment out [super didReceiveMemoryWarning] in
          didReceiveMemoryWarning.

          Here is the repo steps to hit this bug 100% on simulator:

          1. Run your code in simulator, call up camera with navigator.camera.getPicture() to open the album (since camera is not available on simulator)
          2. Simulator > Hardware > Simulate memory warning
          3. Return from the iOS album (either click 'Cancel' or pick a photo)
          4. Observe crash of the app

          This is because the [super didReceiveMemoryWarning] see the web view is running in background (while the album/camera is on) so released it. Later when the album/camera closes and tries to call the JS callback, it cannot find the JS handler and hence crash. Usually in object-c, it is ok to release background views and reconstruct later, just for PhoneGap the web view could not be removed as it is the root view and it has the JS callback to be used later.

          – Yuankai (https://groups.google.com/d/msg/phonegap/ZLbw0s4JREs/Qnl0EwDZ6yMJ)

          Show
          Richard Kimber added a comment - I ran into the same issue and fixed by using the solution suggested by Jonathan Hobson: comment out [super didReceiveMemoryWarning] in didReceiveMemoryWarning. Here is the repo steps to hit this bug 100% on simulator: 1. Run your code in simulator, call up camera with navigator.camera.getPicture() to open the album (since camera is not available on simulator) 2. Simulator > Hardware > Simulate memory warning 3. Return from the iOS album (either click 'Cancel' or pick a photo) 4. Observe crash of the app This is because the [super didReceiveMemoryWarning] see the web view is running in background (while the album/camera is on) so released it. Later when the album/camera closes and tries to call the JS callback, it cannot find the JS handler and hence crash. Usually in object-c, it is ok to release background views and reconstruct later, just for PhoneGap the web view could not be removed as it is the root view and it has the JS callback to be used later. – Yuankai ( https://groups.google.com/d/msg/phonegap/ZLbw0s4JREs/Qnl0EwDZ6yMJ )
          Hide
          Shazron Abdullah added a comment -

          Good observation @YuanKai, and possibly what is happening. What I'm thinking is, since it is EXC_BAD_ACCESS, this usually means a message was sent to an object that was de-allocated, which I believe is the .webView referenced in the plugin (the only webView in the app). The Camera plugin is trying to send this message to the webView property, and it crashes.

          To prevent this crash, the application delegate should set the webView and the webView delegate to nil in viewDidUnload https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVViewController.m#L336 . This would prevent the crash, but of course all your workflow is gone, and most likely not recoverable. Because of the memory purge, it should call viewDidUnload, then viewDidLoad again, and your app should re-load again, starting fresh.

          Ignoring didReceiveMemoryWarning is just a stay of execution, ignored often enough the iOS watchdog will kill your app anyway. Note that all running apps (including Apple's) get this message, not just the current app.

          Show
          Shazron Abdullah added a comment - Good observation @YuanKai, and possibly what is happening. What I'm thinking is, since it is EXC_BAD_ACCESS, this usually means a message was sent to an object that was de-allocated, which I believe is the .webView referenced in the plugin (the only webView in the app). The Camera plugin is trying to send this message to the webView property, and it crashes. To prevent this crash, the application delegate should set the webView and the webView delegate to nil in viewDidUnload https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVViewController.m#L336 . This would prevent the crash, but of course all your workflow is gone, and most likely not recoverable. Because of the memory purge, it should call viewDidUnload, then viewDidLoad again, and your app should re-load again, starting fresh. Ignoring didReceiveMemoryWarning is just a stay of execution, ignored often enough the iOS watchdog will kill your app anyway. Note that all running apps (including Apple's) get this message, not just the current app.
          Hide
          Shazron Abdullah added a comment -

          Following your steps, found the crash: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVCamera.m#L156
          (self.pickerController is nil at this point)

          self.pickerController is nil at this point because CDVCamera's dealloc method was called.
          CDVCamera's dealloc method was called because all the objects in CDVViewController's pluginObjects property (a NSArray) are being purged because of the [super didReceiveMemoryWarning] call. Mystery solved, fix still unknown...

          Show
          Shazron Abdullah added a comment - Following your steps, found the crash: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVCamera.m#L156 (self.pickerController is nil at this point) self.pickerController is nil at this point because CDVCamera's dealloc method was called. CDVCamera's dealloc method was called because all the objects in CDVViewController's pluginObjects property (a NSArray) are being purged because of the [super didReceiveMemoryWarning] call. Mystery solved, fix still unknown...
          Show
          Shazron Abdullah added a comment - Fix commit - http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/499cf514

            People

            • Assignee:
              Shazron Abdullah
              Reporter:
              Richard Kimber
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development