While monitoring Fabric after our most recent release we noticed a new non-fatal crash:
Non-fatal Exception: android.database.CursorWindowAllocationException:
Cursor window allocation of 2048 kb failed.
# Open Cursors=937 (# cursors opened by pid 4459=936)
(# cursors opened by this proc=1)
being thrown when CommCare attempted to save a form. Some Googling confirmed this to have an out of memory exception at its root and indeed the exception reports 936(!) open Cursors. After manually looking through our code I couldn’t find anywhere that we were obviously failing to clean up our Cursors. Further Googling turned up this StackOverflow response with an extremely helpful code snippet:
if (BuildConfig.DEBUG) {
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
This snippet (pasted into the onCreate
of your main Activity
or Application
) enables thread- and VM-level analysis that will crash the application whenever the errors I specified occur (for example, when we’ve lost the handle to a Cursor
or InputStream
without those resources being closed). You could call this the fail very fast principle and this is certainly not something you’d want on in production.
Booting up CommCare I ran into four crashes before even reaching our launch activity. For the most part we were failing to close InputStream
objects and using a try-with-resources
statement fixed the problem.
Interestingly the only dropped Cursor I turned up did not come from our application but was coming from the google_app_measurement_local.db
– looks like a Google problem! Further hunting took me to this discussion implicating firebase
as the culprit, and updating our library resolved the issue.
After poking around our application for a while I was satisfied that I’d exposed and fixed every issue. However, after leaving the tablet dormant for a while a background process kicked in and triggered yet another StrictMode
crash! We’re now debating whether to leave StrictMode
on for all dev builds and looking into logging these events on production builds. I’d be interested to hear others’ best practices on this and I recommend giving this snippet a try for any dev build.
[Photo from the beautiful Sand Dunes National Park]