Work around a dalvik JDWP/GC deadlock.

Also add a few missing TEMP_FAILURE_RETRYs that can cause dalvik to
incorrectly decide that the debugger connection has been broken.

Bug: 8191824
Change-Id: I791b514c6bec1ca634a65d9f87c5fa06da01b5ed
diff --git a/vm/SignalCatcher.cpp b/vm/SignalCatcher.cpp
index a4beb6b..d4302aa 100644
--- a/vm/SignalCatcher.cpp
+++ b/vm/SignalCatcher.cpp
@@ -191,7 +191,7 @@
             ALOGE("Unable to open stack trace file '%s': %s",
                 gDvm.stackTraceFile, strerror(errno));
         } else {
-            ssize_t actual = write(fd, traceBuf, traceLen);
+            ssize_t actual = TEMP_FAILURE_RETRY(write(fd, traceBuf, traceLen));
             if (actual != (ssize_t) traceLen) {
                 ALOGE("Failed to write stack traces to %s (%d of %zd): %s",
                     gDvm.stackTraceFile, (int) actual, traceLen,
diff --git a/vm/alloc/HeapSource.cpp b/vm/alloc/HeapSource.cpp
index ee40af82..93cdd2f 100644
--- a/vm/alloc/HeapSource.cpp
+++ b/vm/alloc/HeapSource.cpp
@@ -457,6 +457,14 @@
             dvmWaitCond(&gHs->gcThreadCond, &gHs->gcThreadMutex);
         }
 
+        // Many JDWP requests cause allocation. We can't take the heap lock and wait to
+        // transition to runnable so we can start a GC if a debugger is connected, because
+        // we don't know that the JDWP thread isn't about to allocate and require the
+        // heap lock itself, leading to deadlock. http://b/8191824.
+        if (gDvm.debuggerConnected) {
+            continue;
+        }
+
         dvmLockHeap();
         /*
          * Another thread may have started a concurrent garbage
diff --git a/vm/jdwp/JdwpAdb.cpp b/vm/jdwp/JdwpAdb.cpp
index 87db1d2..8fb5391 100644
--- a/vm/jdwp/JdwpAdb.cpp
+++ b/vm/jdwp/JdwpAdb.cpp
@@ -345,7 +345,7 @@
 
     if (netState->wakeFds[1] >= 0) {
         ALOGV("+++ writing to wakePipe");
-        write(netState->wakeFds[1], "", 1);
+        TEMP_FAILURE_RETRY(write(netState->wakeFds[1], "", 1));
     }
 }
 
@@ -629,8 +629,8 @@
         }
 
         errno = 0;
-        cc = write(netState->clientSock, netState->inputBuffer,
-                kMagicHandshakeLen);
+        cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer,
+                                      kMagicHandshakeLen));
         if (cc != kMagicHandshakeLen) {
             ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                 strerror(errno), cc, (int) kMagicHandshakeLen);
diff --git a/vm/jdwp/JdwpMain.cpp b/vm/jdwp/JdwpMain.cpp
index 90e4c45..55e278d 100644
--- a/vm/jdwp/JdwpMain.cpp
+++ b/vm/jdwp/JdwpMain.cpp
@@ -45,8 +45,8 @@
 ssize_t JdwpNetStateBase::writePacket(ExpandBuf* pReply)
 {
     dvmDbgLockMutex(&socketLock);
-    ssize_t cc = write(clientSock, expandBufGetBuffer(pReply),
-            expandBufGetLength(pReply));
+    ssize_t cc = TEMP_FAILURE_RETRY(write(clientSock, expandBufGetBuffer(pReply),
+                                          expandBufGetLength(pReply)));
     dvmDbgUnlockMutex(&socketLock);
 
     return cc;
@@ -59,7 +59,7 @@
     int iovcnt)
 {
     dvmDbgLockMutex(&socketLock);
-    ssize_t actual = writev(clientSock, iov, iovcnt);
+    ssize_t actual = TEMP_FAILURE_RETRY(writev(clientSock, iov, iovcnt));
     dvmDbgUnlockMutex(&socketLock);
 
     return actual;
diff --git a/vm/jdwp/JdwpSocket.cpp b/vm/jdwp/JdwpSocket.cpp
index ad0a287..eaea607 100644
--- a/vm/jdwp/JdwpSocket.cpp
+++ b/vm/jdwp/JdwpSocket.cpp
@@ -226,7 +226,7 @@
     /* if we might be sitting in select, kick us loose */
     if (netState->wakePipe[1] >= 0) {
         ALOGV("+++ writing to wakePipe");
-        (void) write(netState->wakePipe[1], "", 1);
+        TEMP_FAILURE_RETRY(write(netState->wakePipe[1], "", 1));
     }
 }
 static void netShutdownExtern(JdwpState* state)
@@ -789,8 +789,8 @@
         }
 
         errno = 0;
-        cc = write(netState->clientSock, netState->inputBuffer,
-                kMagicHandshakeLen);
+        cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer,
+                                      kMagicHandshakeLen));
         if (cc != kMagicHandshakeLen) {
             ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                 strerror(errno), cc, (int) kMagicHandshakeLen);