From fbbea2e1bf85bbee28fe86d1cf912929a8d09f6f Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Thu, 28 Jul 2011 17:59:27 -0700 Subject: 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 --- core/jni/android_bluetooth_BluetoothSocket.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp index 4c84324af266..488b5c249a50 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); -- cgit v1.2.3-59-g8ed1b