From 6568f9fcbc577ba63df2ce576536bf11c8bfd2d5 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 16 Apr 2015 07:22:48 +1000 Subject: [PATCH] Fixed crash on slow device due to database being locked. The error below was happening on my crappy slow phone, I suspect because the database upgrade check was locking the database, while this was scheduled and started running on a different thread. Given it is a very low priority task (it notifies F-Droid if apps were installed by a method other than F-Droid) it is now delayed by 10 seconds. E FATAL EXCEPTION: AsyncTask #1 E java.lang.RuntimeException: An error occured while executing doInBackground() E at android.os.AsyncTask$3.done(AsyncTask.java:200) E at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) E at java.util.concurrent.FutureTask.setException(FutureTask.java:125) E at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) E at java.util.concurrent.FutureTask.run(FutureTask.java:138) E at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) E at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) E at java.lang.Thread.run(Thread.java:1019) E Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE; E at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method) E at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1763) E at android.database.sqlite.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:527) E at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:481) E at org.fdroid.fdroid.data.FDroidProvider.applyBatch(FDroidProvider.java:58) E at android.content.ContentProvider$Transport.applyBatch(ContentProvider.java:217) E at android.content.ContentProviderClient.applyBatch(ContentProviderClient.java:95) E at android.content.ContentResolver.applyBatch(ContentResolver.java:639) E at org.fdroid.fdroid.data.InstalledAppCacheUpdater.updateCache(InstalledAppCacheUpdater.java:98) E at org.fdroid.fdroid.data.InstalledAppCacheUpdater.update(InstalledAppCacheUpdater.java:64) E at org.fdroid.fdroid.data.InstalledAppCacheUpdater$Worker.doInBackground(InstalledAppCacheUpdater.java:163) E at org.fdroid.fdroid.data.InstalledAppCacheUpdater$Worker.doInBackground(InstalledAppCacheUpdater.java:159) E at android.os.AsyncTask$2.call(AsyncTask.java:185) E at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) E ... 4 more --- F-Droid/src/org/fdroid/fdroid/FDroidApp.java | 3 ++- .../fdroid/fdroid/data/InstalledAppCacheUpdater.java | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java index 538bd041b..68ecd85c8 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java @@ -164,7 +164,8 @@ public class FDroidApp extends Application { // e.g. if we crashed/ran out of battery half way through responding // to a package installed intent. It doesn't really matter where // we put this in the bootstrap process, because it runs on a different - // thread. In fact, we may as well start early for this reason. + // thread, which will be delayed by some seconds to avoid an error where + // the database is locked due to the database updater. InstalledAppCacheUpdater.updateInBackground(getApplicationContext()); // If the user changes the preference to do with filtering rooted apps, diff --git a/F-Droid/src/org/fdroid/fdroid/data/InstalledAppCacheUpdater.java b/F-Droid/src/org/fdroid/fdroid/data/InstalledAppCacheUpdater.java index a1fbaa790..d86640da8 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/InstalledAppCacheUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/data/InstalledAppCacheUpdater.java @@ -76,7 +76,7 @@ public class InstalledAppCacheUpdater { } protected void startBackgroundWorker() { - new Worker().execute(); + new PostponedWorker().execute(); } /** @@ -156,10 +156,18 @@ public class InstalledAppCacheUpdater { return ops; } - private class Worker extends AsyncTask { + /** + * Waits 5 seconds before beginning to update cache of installed apps. + * This is due to a bug where the database was locked as F-Droid was starting, + * which caused a crash. + */ + private class PostponedWorker extends AsyncTask { @Override protected Boolean doInBackground(Void... params) { + try { + Thread.sleep(10000); + } catch (InterruptedException e) {} return update(); }