Skip to content
Snippets Groups Projects
Commit e30c0580 authored by Jean Chalard's avatar Jean Chalard
Browse files

Preemptive anti-deadlock device

We don't know of any actual bug in the implementation of the
pool that may result in a deadlock, but this still implements
a means out of a deadlock if one ever arises anyway. It's
meant to improve the resilience of the spell checker.

Bug: 5441027
Change-Id: I689491090792dbb89110ee56631965c5bb2dc712
parent 5d6b8e18
No related branches found
No related tags found
No related merge requests found
......@@ -193,7 +193,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
if (shouldFilterOut(inText, mScript)) {
DictAndProximity dictInfo = null;
try {
dictInfo = mDictionaryPool.takeOrGetNull();
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (null == dictInfo) {
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
}
......@@ -236,7 +236,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
boolean isInDict = true;
DictAndProximity dictInfo = null;
try {
dictInfo = mDictionaryPool.takeOrGetNull();
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (null == dictInfo) {
return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
}
......
......@@ -16,14 +16,24 @@
package com.android.inputmethod.latin.spellcheck;
import android.util.Log;
import java.util.Locale;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* A blocking queue that creates dictionaries up to a certain limit as necessary.
* As a deadlock-detecting device, if waiting for more than TIMEOUT = 3 seconds, we
* will clear the queue and generate its contents again. This is transparent for
* the client code, but may help with sloppy clients.
*/
@SuppressWarnings("serial")
public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
private final static String TAG = DictionaryPool.class.getSimpleName();
// How many seconds we wait for a dictionary to become available. Past this delay, we give up in
// fear some bug caused a deadlock, and reset the whole pool.
private final static int TIMEOUT = 3;
private final AndroidSpellCheckerService mService;
private final int mMaxSize;
private final Locale mLocale;
......@@ -41,13 +51,23 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
}
@Override
public DictAndProximity take() throws InterruptedException {
public DictAndProximity poll(final long timeout, final TimeUnit unit)
throws InterruptedException {
final DictAndProximity dict = poll();
if (null != dict) return dict;
synchronized(this) {
if (mSize >= mMaxSize) {
// Our pool is already full. Wait until some dictionary is ready.
return super.take();
// Our pool is already full. Wait until some dictionary is ready, or TIMEOUT
// expires to avoid a deadlock.
final DictAndProximity result = super.poll(timeout, unit);
if (null == result) {
Log.e(TAG, "Deadlock detected ! Resetting dictionary pool");
clear();
mSize = 1;
return mService.createDictAndProximity(mLocale);
} else {
return result;
}
} else {
++mSize;
return mService.createDictAndProximity(mLocale);
......@@ -56,9 +76,9 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
}
// Convenience method
public DictAndProximity takeOrGetNull() {
public DictAndProximity pollWithDefaultTimeout() {
try {
return take();
return poll(TIMEOUT, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return null;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment