Keystore 2.0: Poll on DB locked.
SQLite2 seems to hold a shared mutex while running the busy handler when
waiting for the database file to become available. This makes it
impossible to successfully recover from a locked database when the
transaction holding the device busy is in the same process on a
different connection. As a result the busy hander has to time out and
fail in order to make progress.
This patch replaces the default busy handler with one that times out
immediately. In addition all database accesses have been moved into
retry loops that handle the busy error which can occur at any time, not
only during begin or commit of a transaction. This assures that no
sqlite3 internal mutexes are held while waiting for the database to
become available.
The database interface had to change slightly to assure that all
database manipulations can be replayed and not data is lost.
A test has been added that makes sure that the correct error is caught,
and another test was added that produces a lot of concurrent database
manipulations and would easily trigger database busy errors.
Test: keystore2_test
Change-Id: I8ce3e3159b2356ace2b9f0ebdf074bbabc6612af
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index ec133f8..cc1da98 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -144,7 +144,7 @@
let mut db = db.borrow_mut();
let (need_gc, key_id) = db
.store_new_key(
- key,
+ &key,
&key_parameters,
&key_blob,
&cert_info,
@@ -207,7 +207,7 @@
let (key_id_guard, mut key_entry) = DB
.with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
db.borrow_mut().load_key_entry(
- key.clone(),
+ &key,
KeyType::Client,
KeyEntryLoadBits::KM,
caller_uid,
@@ -485,7 +485,7 @@
let (wrapping_key_id_guard, wrapping_key_entry) = DB
.with(|db| {
db.borrow_mut().load_key_entry(
- wrapping_key.clone(),
+ &wrapping_key,
KeyType::Client,
KeyEntryLoadBits::KM,
caller_uid,