summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoachim Sauer <jsauer@google.com>2016-08-18 12:26:39 +0100
committerJoachim Sauer <jsauer@google.com>2016-08-19 11:18:50 +0100
commit35a16e21d16dd42c7ff7cd5a4e0976206522897c (patch)
tree8f2cebb7f71b53f3f234ec631a150f7b3fd41e84
parent77fddf01ddabd0a77745d1b902badf51901e9077 (diff)
downloadandroid_external_icu-35a16e21d16dd42c7ff7cd5a4e0976206522897c.tar.gz
android_external_icu-35a16e21d16dd42c7ff7cd5a4e0976206522897c.tar.bz2
android_external_icu-35a16e21d16dd42c7ff7cd5a4e0976206522897c.zip
Fix deadlock between java.util and ICU TimeZone.
There was a deadlock between java.util.TimeZone.setDefault() and android.icu.util.TimeZone.getDefault(): - the former would lock on j.u.TimeZone.class and the call the synchronized a.i.u.TimeZone.clearCachedDefault() - the latter would synchronize on a.i.u.TimeZone and then call the synchronized j.u.TimeZone.getDefault To ensure every path synchronizes on objects in the same order, this change adds an explicit synchronize block on j.u.TimeZone in a.i.u.TimeZone.getDefault(). TimeZoneTest.testSetDefaultDeadlock() is a probabilistic test that was able to reproduce the problem roughly 8 times out of 10. Bug: 30937209 Test: libcore/run-libcore-tests libcore.java.util org.apache.harmony.tests.java.util (cherry picked from commit 15c4b7460a92a69ca40db46baf17e205421fa8a1) (cherry picked from commit df87c613a2f92f0df9f6b146c2bac03f5e3cb868) Change-Id: Ic16fbd6b0e75243cd93628eed7d18c34a70378c6
-rw-r--r--android_icu4j/src/main/java/android/icu/util/TimeZone.java24
-rw-r--r--icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java24
2 files changed, 34 insertions, 14 deletions
diff --git a/android_icu4j/src/main/java/android/icu/util/TimeZone.java b/android_icu4j/src/main/java/android/icu/util/TimeZone.java
index 27f2eec05..7b64afeb2 100644
--- a/android_icu4j/src/main/java/android/icu/util/TimeZone.java
+++ b/android_icu4j/src/main/java/android/icu/util/TimeZone.java
@@ -845,16 +845,26 @@ abstract public class TimeZone implements Serializable, Cloneable, Freezable<Tim
*/
public static TimeZone getDefault() {
if (defaultZone == null) {
- synchronized(TimeZone.class) {
- if (defaultZone == null) {
- if (TZ_IMPL == TIMEZONE_JDK) {
- defaultZone = new JavaTimeZone();
- } else {
- java.util.TimeZone temp = java.util.TimeZone.getDefault();
- defaultZone = getFrozenTimeZone(temp.getID());
+ // Android patch (http://b/30937209) start.
+ // Avoid a deadlock by always acquiring monitors in order (1) java.util.TimeZone.class
+ // then (2) icu.util.TimeZone.class and not (2) then (1).
+ // Without the synchronized here there is a possible deadlock between threads calling
+ // this method and other threads calling methods on java.util.TimeZone. e.g.
+ // java.util.TimeZone.setDefault() calls back into
+ // icu.util.TimeZone.clearCachedDefault() so always acquires them in order (1) then (2).
+ synchronized (java.util.TimeZone.class) {
+ synchronized (TimeZone.class) {
+ if (defaultZone == null) {
+ if (TZ_IMPL == TIMEZONE_JDK) {
+ defaultZone = new JavaTimeZone();
+ } else {
+ java.util.TimeZone temp = java.util.TimeZone.getDefault();
+ defaultZone = getFrozenTimeZone(temp.getID());
+ }
}
}
}
+ // Android patch (http://b/30937209) end.
}
return defaultZone.cloneAsThawed();
}
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
index dc9b7d345..6a37b3629 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
@@ -922,16 +922,26 @@ abstract public class TimeZone implements Serializable, Cloneable, Freezable<Tim
*/
public static TimeZone getDefault() {
if (defaultZone == null) {
- synchronized(TimeZone.class) {
- if (defaultZone == null) {
- if (TZ_IMPL == TIMEZONE_JDK) {
- defaultZone = new JavaTimeZone();
- } else {
- java.util.TimeZone temp = java.util.TimeZone.getDefault();
- defaultZone = getFrozenTimeZone(temp.getID());
+ // Android patch (http://b/30937209) start.
+ // Avoid a deadlock by always acquiring monitors in order (1) java.util.TimeZone.class
+ // then (2) icu.util.TimeZone.class and not (2) then (1).
+ // Without the synchronized here there is a possible deadlock between threads calling
+ // this method and other threads calling methods on java.util.TimeZone. e.g.
+ // java.util.TimeZone.setDefault() calls back into
+ // icu.util.TimeZone.clearCachedDefault() so always acquires them in order (1) then (2).
+ synchronized (java.util.TimeZone.class) {
+ synchronized (TimeZone.class) {
+ if (defaultZone == null) {
+ if (TZ_IMPL == TIMEZONE_JDK) {
+ defaultZone = new JavaTimeZone();
+ } else {
+ java.util.TimeZone temp = java.util.TimeZone.getDefault();
+ defaultZone = getFrozenTimeZone(temp.getID());
+ }
}
}
}
+ // Android patch (http://b/30937209) end.
}
return defaultZone.cloneAsThawed();
}