From 14c9137a337893d63b589b3a8174868fa5183a57 Mon Sep 17 00:00:00 2001 From: Sam Judd Date: Sun, 26 Nov 2017 19:15:22 -0800 Subject: [PATCH] Avoid IOExceptions in delete() when the cache dir is deleted externally. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit listFiles() will return null if the directory has been deleted. This scenario isn’t totally far fetched because it’s fairly common for Android developers to place their disk caches in the Android application cache directory. The cache directory can be cleared at any time by the system, including while the app is open, which in turn can cause unexpected IOExceptions when delete() is called. See https://github.com/bumptech/glide/issues/2465 for additional context. --- .../com/jakewharton/disklrucache/Util.java | 3 ++ .../disklrucache/DiskLruCacheTest.java | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/main/java/com/jakewharton/disklrucache/Util.java b/src/main/java/com/jakewharton/disklrucache/Util.java index 0a7dba9..cc61711 100644 --- a/src/main/java/com/jakewharton/disklrucache/Util.java +++ b/src/main/java/com/jakewharton/disklrucache/Util.java @@ -50,6 +50,9 @@ static String readFully(Reader reader) throws IOException { * could not be deleted, or if {@code dir} is not a readable directory. */ static void deleteContents(File dir) throws IOException { + if (!dir.exists()) { + return; + } File[] files = dir.listFiles(); if (files == null) { throw new IOException("not a readable directory: " + dir); diff --git a/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java b/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java index 6735179..553a434 100644 --- a/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java +++ b/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java @@ -21,6 +21,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.InputStream; +import java.io.IOException; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; @@ -885,6 +886,42 @@ public final class DiskLruCacheTest { assertThat(cache.get("a")).isNull(); } + @Test public void deleteAfterCacheDirectoryIsDeletedExternallyDoesNotThrow() + throws IOException { + FileUtils.deleteDirectory(cacheDir); + cache.delete(); + } + + @Test public void deleteWithNotReadableCacheDirectoryThowsIOException() + throws IOException { + try { + if (!cacheDir.setReadable(false)) { + fail("Unable to set writable on: " + cacheDir); + } + cache.delete(); + fail("Expected delete to throw"); + } catch (IOException e) { + // Expected. + } finally { + cacheDir.setReadable(true); + } + } + + @Test public void deleteWithNotWritableCacheDirectoryThowsIOException() + throws IOException { + try { + if (!cacheDir.setWritable(false)) { + fail("Unable to set writable on: " + cacheDir); + } + cache.delete(); + fail("Expected delete to throw"); + } catch (IOException e) { + // Expected. + } finally { + cacheDir.setWritable(true); + } + } + private void assertJournalEquals(String... expectedBodyLines) throws Exception { List expectedLines = new ArrayList(); expectedLines.add(MAGIC);