diff options
author | Nick Pelly <npelly@google.com> | 2011-07-28 17:59:27 -0700 |
---|---|---|
committer | Nick Pelly <npelly@google.com> | 2011-07-28 18:11:34 -0700 |
commit | fbbea2e1bf85bbee28fe86d1cf912929a8d09f6f (patch) | |
tree | acf8677c9565cf3bff0bd492c2177c6107f363e8 /core/jni | |
parent | 3ebdb48921c49ae172d094463ed97361328aa4b2 (diff) | |
download | frameworks_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.cpp | 24 |
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); |