summaryrefslogtreecommitdiffstats
path: root/core/java/android/database
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2013-01-07 17:15:12 -0800
committerJeff Brown <jeffbrown@google.com>2013-01-08 15:32:50 -0800
commitc21b5a019c1da00b6d861cd2859e3c349a44b3a7 (patch)
tree750072f97e644448c149c8d5447d514cca189ba0 /core/java/android/database
parentf6f00b14fb4d2a247393fd3e6d45de077a8b4da9 (diff)
downloadframeworks_base-c21b5a019c1da00b6d861cd2859e3c349a44b3a7.zip
frameworks_base-c21b5a019c1da00b6d861cd2859e3c349a44b3a7.tar.gz
frameworks_base-c21b5a019c1da00b6d861cd2859e3c349a44b3a7.tar.bz2
Fix cursor window leak when query execution fails.
Ensure that the Cursor object is closed if a query on a content provider fails due to an error or is canceled during execution. There are several places in the code where similar problems can occur. To further reduce the likelihood of leaks, close the cursor window immediately when a query fails. Bug: 7278577 Change-Id: I8c686c259de80a162b9086628a817d57f09fdd13
Diffstat (limited to 'core/java/android/database')
-rw-r--r--core/java/android/database/CursorToBulkCursorAdaptor.java5
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java29
2 files changed, 24 insertions, 10 deletions
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
index 525be96..82a61d4 100644
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ b/core/java/android/database/CursorToBulkCursorAdaptor.java
@@ -132,6 +132,11 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
}
}
+ /**
+ * Returns an object that contains sufficient metadata to reconstruct
+ * the cursor remotely. May throw if an error occurs when executing the query
+ * and obtaining the row count.
+ */
public BulkCursorDescriptor getBulkCursorDescriptor() {
synchronized (mLock) {
throwIfCursorIsClosed();
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index b29897e..5a1a8e2 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -138,17 +138,26 @@ public class SQLiteCursor extends AbstractWindowedCursor {
private void fillWindow(int requiredPos) {
clearOrCreateWindow(getDatabase().getPath());
- if (mCount == NO_COUNT) {
- int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0);
- mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true);
- mCursorWindowCapacity = mWindow.getNumRows();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "received count(*) from native_fill_window: " + mCount);
+ try {
+ if (mCount == NO_COUNT) {
+ int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0);
+ mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true);
+ mCursorWindowCapacity = mWindow.getNumRows();
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "received count(*) from native_fill_window: " + mCount);
+ }
+ } else {
+ int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos,
+ mCursorWindowCapacity);
+ mQuery.fillWindow(mWindow, startPos, requiredPos, false);
}
- } else {
- int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos,
- mCursorWindowCapacity);
- mQuery.fillWindow(mWindow, startPos, requiredPos, false);
+ } catch (RuntimeException ex) {
+ // Close the cursor window if the query failed and therefore will
+ // not produce any results. This helps to avoid accidentally leaking
+ // the cursor window if the client does not correctly handle exceptions
+ // and fails to close the cursor.
+ closeWindow();
+ throw ex;
}
}