From dd28b7b5f33810666919e2f9fc8deb27b7b9c169 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 24 Aug 2016 14:54:20 -0700 Subject: [PATCH] Try to mitigate issue #31016187: system_server crash in ArraySet. Instead of crashing, log a wtf and recover. This is not a problem in ArraySet, but caused by someone else using an ArraySet without protecting access to it. So whoever is calling at this point is not the cause, and it isn't worthwhile to let them crash. Change-Id: Iaefa4315b620c9fe24b31507e4aa47a8525c8540 (cherry picked from commit 92aa4b2ba3c93cc344c885b50b75726599e6065d) --- core/java/android/util/ArraySet.java | 50 +++++++++++++++++++--------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index 1e765b62e131f..a02c070d4889f 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -156,28 +156,46 @@ public final class ArraySet implements Collection, Set { synchronized (ArraySet.class) { if (mTwiceBaseCache != null) { final Object[] array = mTwiceBaseCache; - mArray = array; - mTwiceBaseCache = (Object[])array[0]; - mHashes = (int[])array[1]; - array[0] = array[1] = null; - mTwiceBaseCacheSize--; - if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes - + " now have " + mTwiceBaseCacheSize + " entries"); - return; + try { + mArray = array; + mTwiceBaseCache = (Object[]) array[0]; + mHashes = (int[]) array[1]; + array[0] = array[1] = null; + mTwiceBaseCacheSize--; + if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes + + " now have " + mTwiceBaseCacheSize + " entries"); + return; + } catch (ClassCastException e) { + } + // Whoops! Someone trampled the array (probably due to not protecting + // their access with a lock). Our cache is corrupt; report and give up. + Slog.wtf(TAG, "Found corrupt ArraySet cache: [0]=" + array[0] + + " [1]=" + array[1]); + mTwiceBaseCache = null; + mTwiceBaseCacheSize = 0; } } } else if (size == BASE_SIZE) { synchronized (ArraySet.class) { if (mBaseCache != null) { final Object[] array = mBaseCache; - mArray = array; - mBaseCache = (Object[])array[0]; - mHashes = (int[])array[1]; - array[0] = array[1] = null; - mBaseCacheSize--; - if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes - + " now have " + mBaseCacheSize + " entries"); - return; + try { + mArray = array; + mBaseCache = (Object[]) array[0]; + mHashes = (int[]) array[1]; + array[0] = array[1] = null; + mBaseCacheSize--; + if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes + + " now have " + mBaseCacheSize + " entries"); + return; + } catch (ClassCastException e) { + } + // Whoops! Someone trampled the array (probably due to not protecting + // their access with a lock). Our cache is corrupt; report and give up. + Slog.wtf(TAG, "Found corrupt ArraySet cache: [0]=" + array[0] + + " [1]=" + array[1]); + mBaseCache = null; + mBaseCacheSize = 0; } } }