summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorNick Pelly <npelly@google.com>2011-07-28 17:59:27 -0700
committerNick Pelly <npelly@google.com>2011-07-28 18:11:34 -0700
commitfbbea2e1bf85bbee28fe86d1cf912929a8d09f6f (patch)
treeacf8677c9565cf3bff0bd492c2177c6107f363e8 /core/jni
parent3ebdb48921c49ae172d094463ed97361328aa4b2 (diff)
downloadframeworks_base-fbbea2e1bf85bbee28fe86d1cf912929a8d09f6f.zip
frameworks_base-fbbea2e1bf85bbee28fe86d1cf912929a8d09f6f.tar.gz
frameworks_base-fbbea2e1bf85bbee28fe86d1cf912929a8d09f6f.tar.bz2
Workaround for bug 5082381 (EALREADY on ACL collision).
If connect() fails with EALREADY, then retry. Unfortunately we also need to switch to a new FD. This is currently safe, but its a little fragile to changes in the code (especially if we ever expose the fd to applications) so it would be great to fix this issue properly in the kernel sometime and revert this commit. Change-Id: I12fb6b7f2b8ca40f425f66b504754048c9460329
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/android_bluetooth_BluetoothSocket.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index 4c84324..488b5c2 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -57,6 +57,9 @@ static const int TYPE_L2CAP = 3; // TODO: Test l2cap code paths
static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer
+static void abortNative(JNIEnv *env, jobject obj);
+static void destroyNative(JNIEnv *env, jobject obj);
+
static struct asocket *get_socketData(JNIEnv *env, jobject obj) {
struct asocket *s =
(struct asocket *) env->GetIntField(obj, field_mSocketData);
@@ -172,6 +175,7 @@ static void connectNative(JNIEnv *env, jobject obj) {
socklen_t addr_sz;
struct sockaddr *addr;
struct asocket *s = get_socketData(env, obj);
+ int retry = 0;
if (!s)
return;
@@ -226,10 +230,30 @@ static void connectNative(JNIEnv *env, jobject obj) {
return;
}
+connect:
ret = asocket_connect(s, addr, addr_sz, -1);
LOGV("...connect(%d, %s) = %d (errno %d)",
s->fd, TYPE_AS_STR(type), ret, errno);
+ if (ret && errno == EALREADY && retry < 2) {
+ /* workaround for bug 5082381 (EALREADY on ACL collision):
+ * retry the connect. Unfortunately we have to create a new fd.
+ * It's not ideal to switch the fd underneath the object, but
+ * is currently safe */
+ LOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround");
+ usleep(100000);
+ retry++;
+ abortNative(env, obj);
+ destroyNative(env, obj);
+ initSocketNative(env, obj);
+ if (env->ExceptionOccurred()) {
+ return;
+ }
+ goto connect;
+ }
+ if (!ret && retry > 0)
+ LOGD("...workaround ok");
+
if (ret)
jniThrowIOException(env, errno);