From dacebceff67568fab8505c6ce5d99f801f93d90e Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 28 Feb 2017 16:01:05 +1100 Subject: [PATCH 1/2] Ignore errors that are likely due to filesystem corruption. There is a specific POSIX error "EIO" which seems to be the "general purpose we don't know what went wrong but its probably bad" exception. Our investigations in #855 resulted in the conclusion that it is likely due to some sort of filesystem corruption or something like that. Either way, it is annoying many people, so we need to prevent it or ignore it, rather than prompting the user to submit a bug report. After much investigation it was unable to be reproduced other than by one of the original bug reporters. As such, this change ignores it. Unfortunately Java `IOException`s don't have an API for getting the errno of a POSIX IO error. Thus, this change results to parsing the exception message instead :( Fixes #855. --- app/src/main/java/org/fdroid/fdroid/Utils.java | 18 +++++++++++++++++- .../data/InstalledAppProviderService.java | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index d44231436..52a8b5441 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -417,13 +417,29 @@ public final class Utils { byte[] mdbytes = md.digest(); return toHexString(mdbytes).toLowerCase(Locale.ENGLISH); - } catch (IOException | NoSuchAlgorithmException e) { + } catch (IOException e) { + // The annoyance (potentially) caused by miscellaneous filesystem corruption results in + // F-Droid constantly popping up crash reports when F-Droid isn't even open. As such this + // exception-message-parsing-and-throwing-a-new-ignorable-exception-hackery is probably + // warranted. See https://www.gitlab.com/fdroid/fdroidclient/issues/855 for more detail. + if (e.getMessage().contains("read failed: EIO (I/O error)")) { + throw new PotentialFilesystemCorruptionException(e); + } + + throw new IllegalArgumentException(e); + } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } finally { closeQuietly(fis); } } + public static class PotentialFilesystemCorruptionException extends IllegalArgumentException { + public PotentialFilesystemCorruptionException(IOException e) { + super(e); + } + } + /** * Computes the base 16 representation of the byte array argument. * diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index 6dcc83e33..54bf64d6f 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -249,6 +249,13 @@ public class InstalledAppProviderService extends IntentService { } insertAppIntoDb(this, packageInfo, hashType, hash); + } catch (Utils.PotentialFilesystemCorruptionException e) { + Log.e(TAG, "Encountered potential filesystem corruption, or other unknown " + + "problem when calculating hash of " + apk.getAbsolutePath() + ". " + + "It is unlikely F-Droid can do anything about this, and this " + + "likely happened in the background. As such, we will continue without " + + "interrupting the user by asking them to send a crash report."); + return; } catch (IllegalArgumentException e) { Utils.debugLog(TAG, e.getMessage()); ACRA.getErrorReporter().handleException(e, false); From 9cc66e035ad4b6cd2b9ea5fcf0868a4e9d2935c2 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 12 Sep 2017 21:44:48 +0200 Subject: [PATCH 2/2] show Toast if InstalledAppProviderService encounters EIO errors A notification would be better, but a Toast is better than nothing. --- .../data/InstalledAppProviderService.java | 24 ++++++++++--------- app/src/main/res/values/strings.xml | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index 54bf64d6f..5b2aaec29 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -11,12 +11,16 @@ import android.net.Uri; import android.os.Process; import android.support.annotation.Nullable; import android.util.Log; - +import android.widget.Toast; import org.acra.ACRA; import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.Hasher; +import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Schema.InstalledAppTable; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subjects.PublishSubject; import java.io.File; import java.io.FilenameFilter; @@ -25,10 +29,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import rx.functions.Action1; -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - /** * Handles all updates to {@link InstalledAppProvider}, whether checking the contents * versus what Android says is installed, or processing {@link Intent}s that come @@ -76,12 +76,12 @@ public class InstalledAppProviderService extends IntentService { .subscribeOn(Schedulers.newThread()) .debounce(3, TimeUnit.SECONDS) .subscribe(new Action1() { - @Override - public void call(String packageName) { - Utils.debugLog(TAG, "Notifying content providers (so they can update the relevant views)."); - getContentResolver().notifyChange(AppProvider.getContentUri(), null); - getContentResolver().notifyChange(ApkProvider.getContentUri(), null); - } + @Override + public void call(String packageName) { + Utils.debugLog(TAG, "Notifying content providers (so they can update the relevant views)."); + getContentResolver().notifyChange(AppProvider.getContentUri(), null); + getContentResolver().notifyChange(ApkProvider.getContentUri(), null); + } }); // ...alternatively, this non-debounced version will instantly emit an event about the @@ -250,6 +250,8 @@ public class InstalledAppProviderService extends IntentService { insertAppIntoDb(this, packageInfo, hashType, hash); } catch (Utils.PotentialFilesystemCorruptionException e) { + String msg = getString(R.string.installed_app__file_corrupt, apk.getAbsolutePath()); + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); Log.e(TAG, "Encountered potential filesystem corruption, or other unknown " + "problem when calculating hash of " + apk.getAbsolutePath() + ". " + "It is unlikely F-Droid can do anything about this, and this " + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ab5e19c1c..d7f811eaf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -93,6 +93,7 @@ This often occurs with apps installed via Google Play or other sources, if they Updates ignored for Version %1$s + F-Droid received EIO error: %s is probably corrupt! Download Download all updates