OSDN Git Service

Work around a dalvik JDWP/GC deadlock.
[android-x86/dalvik.git] / vm / jdwp / JdwpAdb.cpp
index 4614069..8fb5391 100644 (file)
@@ -47,9 +47,8 @@
 #define kJdwpControlName    "\0jdwp-control"
 #define kJdwpControlNameLen (sizeof(kJdwpControlName)-1)
 
-struct JdwpNetState {
+struct JdwpNetState : public JdwpNetStateBase {
     int                 controlSock;
-    int                 clientSock;
     bool                awaitingHandshake;
     bool                shuttingDown;
     int                 wakeFds[2];
@@ -62,6 +61,23 @@ struct JdwpNetState {
         struct sockaddr_un  controlAddrUn;
         struct sockaddr     controlAddrPlain;
     } controlAddr;
+
+    JdwpNetState()
+    {
+        controlSock = -1;
+        awaitingHandshake = false;
+        shuttingDown = false;
+        wakeFds[0] = -1;
+        wakeFds[1] = -1;
+
+        inputCount = 0;
+
+        controlAddr.controlAddrUn.sun_family = AF_UNIX;
+        controlAddrLen = sizeof(controlAddr.controlAddrUn.sun_family) +
+                kJdwpControlNameLen;
+        memcpy(controlAddr.controlAddrUn.sun_path, kJdwpControlName,
+                kJdwpControlNameLen);
+    }
 };
 
 static void
@@ -87,32 +103,9 @@ adbStateFree( JdwpNetState*  netState )
         netState->wakeFds[1] = -1;
     }
 
-    free(netState);
-}
-
-
-static JdwpNetState* adbStateAlloc()
-{
-    JdwpNetState* netState = (JdwpNetState*) calloc(sizeof(*netState),1);
-
-    netState->controlSock = -1;
-    netState->clientSock  = -1;
-
-    netState->controlAddr.controlAddrUn.sun_family = AF_UNIX;
-    netState->controlAddrLen =
-            sizeof(netState->controlAddr.controlAddrUn.sun_family) +
-            kJdwpControlNameLen;
-
-    memcpy(netState->controlAddr.controlAddrUn.sun_path,
-           kJdwpControlName, kJdwpControlNameLen);
-
-    netState->wakeFds[0] = -1;
-    netState->wakeFds[1] = -1;
-
-    return netState;
+    delete netState;
 }
 
-
 /*
  * Do initial prep work, e.g. binding to ports and opening files.  This
  * runs in the main thread, before the JDWP thread starts, so it shouldn't
@@ -122,9 +115,9 @@ static bool startup(struct JdwpState* state, const JdwpStartupParams* pParams)
 {
     JdwpNetState*  netState;
 
-    LOGV("ADB transport startup\n");
+    ALOGV("ADB transport startup");
 
-    state->netState = netState = adbStateAlloc();
+    state->netState = netState = new JdwpNetState;
     if (netState == NULL)
         return false;
 
@@ -172,10 +165,8 @@ static int  receiveClientFd(JdwpNetState*  netState)
 
     if (ret <= 0) {
         if (ret < 0) {
-            LOGW("receiving file descriptor from ADB failed (socket %d): %s\n",
+            ALOGW("receiving file descriptor from ADB failed (socket %d): %s",
                  netState->controlSock, strerror(errno));
-        } else {
-            LOGD("adbd disconnected\n");
         }
         close(netState->controlSock);
         netState->controlSock = -1;
@@ -210,13 +201,13 @@ retry:
 
         netState->controlSock = socket(PF_UNIX, SOCK_STREAM, 0);
         if (netState->controlSock < 0) {
-            LOGE("Could not create ADB control socket:%s\n",
+            ALOGE("Could not create ADB control socket:%s",
                  strerror(errno));
             return false;
         }
 
         if (pipe(netState->wakeFds) < 0) {
-            LOGE("pipe failed");
+            ALOGE("pipe failed");
             return false;
         }
 
@@ -243,7 +234,7 @@ retry:
             if (!ret) {
                 if (!socket_peer_is_trusted(netState->controlSock)) {
                     if (shutdown(netState->controlSock, SHUT_RDWR)) {
-                        LOGE("trouble shutting down socket: %s", strerror(errno));
+                        ALOGE("trouble shutting down socket: %s", strerror(errno));
                     }
                     return false;
                 }
@@ -254,15 +245,15 @@ retry:
                 } while (ret < 0 && errno == EINTR);
 
                 if (ret >= 0) {
-                    LOGV("PID sent as '%.*s' to ADB\n", 4, buff);
+                    ALOGV("PID sent as '%.*s' to ADB", 4, buff);
                     break;
                 }
 
-                LOGE("Weird, can't send JDWP process pid to ADB: %s\n",
+                ALOGE("Weird, can't send JDWP process pid to ADB: %s",
                      strerror(errno));
                 return false;
             }
-            LOGV("Can't connect to ADB control socket:%s\n",
+            ALOGV("Can't connect to ADB control socket:%s",
                  strerror(errno));
 
             usleep( sleep_ms*1000 );
@@ -270,10 +261,13 @@ retry:
             sleep_ms += (sleep_ms >> 1);
             if (sleep_ms > sleep_max_ms)
                 sleep_ms = sleep_max_ms;
+
+            if (netState->shuttingDown)
+                return false;
         }
     }
 
-    LOGV("trying to receive file descriptor from ADB\n");
+    ALOGV("trying to receive file descriptor from ADB");
     /* now we can receive a client file descriptor */
     netState->clientSock = receiveClientFd(netState);
     if (netState->shuttingDown)
@@ -281,12 +275,12 @@ retry:
 
     if (netState->clientSock < 0) {
         if (++retryCount > 5) {
-            LOGE("adb connection max retries exceeded\n");
+            ALOGE("adb connection max retries exceeded");
             return false;
         }
         goto retry;
     } else {
-        LOGV("received file descriptor %d from ADB\n", netState->clientSock);
+        ALOGV("received file descriptor %d from ADB", netState->clientSock);
         netState->awaitingHandshake = 1;
         netState->inputCount = 0;
         return true;
@@ -315,7 +309,7 @@ static void closeConnection(struct JdwpState* state)
     if (netState->clientSock < 0)
         return;
 
-    LOGV("+++ closed JDWP <-> ADB connection\n");
+    ALOGV("+++ closed JDWP <-> ADB connection");
 
     close(netState->clientSock);
     netState->clientSock = -1;
@@ -350,8 +344,8 @@ static void adbStateShutdown(struct JdwpNetState* netState)
     }
 
     if (netState->wakeFds[1] >= 0) {
-        LOGV("+++ writing to wakePipe\n");
-        write(netState->wakeFds[1], "", 1);
+        ALOGV("+++ writing to wakePipe");
+        TEMP_FAILURE_RETRY(write(netState->wakeFds[1], "", 1));
     }
 }
 
@@ -466,30 +460,23 @@ static bool handlePacket(JdwpState* state)
         hdr.cmd = cmd;
         dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply);
         if (expandBufGetLength(pReply) > 0) {
-            int cc;
+            ssize_t cc = netState->writePacket(pReply);
 
-            /*
-             * TODO: we currently assume the write() will complete in one
-             * go, which may not be safe for a network socket.  We may need
-             * to mutex this against sendRequest().
-             */
-            cc = write(netState->clientSock, expandBufGetBuffer(pReply),
-                    expandBufGetLength(pReply));
-            if (cc != (int) expandBufGetLength(pReply)) {
-                LOGE("Failed sending reply to debugger: %s\n", strerror(errno));
+            if (cc != (ssize_t) expandBufGetLength(pReply)) {
+                ALOGE("Failed sending reply to debugger: %s", strerror(errno));
                 expandBufFree(pReply);
                 return false;
             }
         } else {
-            LOGW("No reply created for set=%d cmd=%d\n", cmdSet, cmd);
+            ALOGW("No reply created for set=%d cmd=%d", cmdSet, cmd);
         }
         expandBufFree(pReply);
     } else {
-        LOGV("reply?!\n");
+        ALOGV("reply?!");
         assert(false);
     }
 
-    LOGV("----------\n");
+    ALOGV("----------");
 
     consumeBytes(netState, length);
     return true;
@@ -547,11 +534,11 @@ static bool processIncoming(JdwpState* state)
                 if (maxfd < fd)
                     maxfd = fd;
             } else {
-                LOGI("NOTE: entering select w/o wakepipe\n");
+                ALOGI("NOTE: entering select w/o wakepipe");
             }
 
             if (maxfd < 0) {
-                LOGV("+++ all fds are closed\n");
+                ALOGV("+++ all fds are closed");
                 return false;
             }
 
@@ -571,14 +558,14 @@ static bool processIncoming(JdwpState* state)
             if (selCount < 0) {
                 if (errno == EINTR)
                     continue;
-                LOGE("select failed: %s\n", strerror(errno));
+                ALOGE("select failed: %s", strerror(errno));
                 goto fail;
             }
 
             if (netState->wakeFds[0] >= 0 &&
                 FD_ISSET(netState->wakeFds[0], &readfds))
             {
-                LOGD("Got wake-up signal, bailing out of select\n");
+                ALOGD("Got wake-up signal, bailing out of select");
                 goto fail;
             }
             if (netState->controlSock >= 0 &&
@@ -586,7 +573,7 @@ static bool processIncoming(JdwpState* state)
             {
                 int  sock = receiveClientFd(netState);
                 if (sock >= 0) {
-                    LOGI("Ignoring second debugger -- accepting and dropping\n");
+                    ALOGI("Ignoring second debugger -- accepting and dropping");
                     close(sock);
                 } else {
                     assert(netState->controlSock < 0);
@@ -607,11 +594,11 @@ static bool processIncoming(JdwpState* state)
                     /* read failed */
                     if (errno != EINTR)
                         goto fail;
-                    LOGD("+++ EINTR hit\n");
+                    ALOGD("+++ EINTR hit");
                     return true;
                 } else if (readCount == 0) {
                     /* EOF hit -- far end went away */
-                    LOGV("+++ peer disconnected\n");
+                    ALOGV("+++ peer disconnected");
                     goto fail;
                 } else
                     break;
@@ -637,22 +624,22 @@ static bool processIncoming(JdwpState* state)
         if (memcmp(netState->inputBuffer,
                 kMagicHandshake, kMagicHandshakeLen) != 0)
         {
-            LOGE("ERROR: bad handshake '%.14s'\n", netState->inputBuffer);
+            ALOGE("ERROR: bad handshake '%.14s'", netState->inputBuffer);
             goto fail;
         }
 
         errno = 0;
-        cc = write(netState->clientSock, netState->inputBuffer,
-                kMagicHandshakeLen);
+        cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer,
+                                      kMagicHandshakeLen));
         if (cc != kMagicHandshakeLen) {
-            LOGE("Failed writing handshake bytes: %s (%d of %d)\n",
+            ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                 strerror(errno), cc, (int) kMagicHandshakeLen);
             goto fail;
         }
 
         consumeBytes(netState, kMagicHandshakeLen);
         netState->awaitingHandshake = false;
-        LOGV("+++ handshake complete\n");
+        ALOGV("+++ handshake complete");
         return true;
     }
 
@@ -677,25 +664,20 @@ fail:
 static bool sendRequest(JdwpState* state, ExpandBuf* pReq)
 {
     JdwpNetState* netState = state->netState;
-    int cc;
 
     if (netState->clientSock < 0) {
         /* can happen with some DDMS events */
-        LOGV("NOT sending request -- no debugger is attached\n");
+        ALOGV("NOT sending request -- no debugger is attached");
         return false;
     }
 
-    /*
-     * TODO: we currently assume the write() will complete in one
-     * go, which may not be safe for a network socket.  We may need
-     * to mutex this against handlePacket().
-     */
     errno = 0;
-    cc = write(netState->clientSock, expandBufGetBuffer(pReq),
-            expandBufGetLength(pReq));
-    if (cc != (int) expandBufGetLength(pReq)) {
-        LOGE("Failed sending req to debugger: %s (%d of %d)\n",
-            strerror(errno), cc, (int) expandBufGetLength(pReq));
+
+    ssize_t cc = netState->writePacket(pReq);
+
+    if (cc != (ssize_t) expandBufGetLength(pReq)) {
+        ALOGE("Failed sending req to debugger: %s (%d of %d)",
+            strerror(errno), (int) cc, (int) expandBufGetLength(pReq));
         return false;
     }
 
@@ -717,7 +699,7 @@ static bool sendBufferedRequest(JdwpState* state, const struct iovec* iov,
 
     if (netState->clientSock < 0) {
         /* can happen with some DDMS events */
-        LOGV("NOT sending request -- no debugger is attached\n");
+        ALOGV("NOT sending request -- no debugger is attached");
         return false;
     }
 
@@ -726,15 +708,10 @@ static bool sendBufferedRequest(JdwpState* state, const struct iovec* iov,
     for (i = 0; i < iovcnt; i++)
         expected += iov[i].iov_len;
 
-    /*
-     * TODO: we currently assume the writev() will complete in one
-     * go, which may not be safe for a network socket.  We may need
-     * to mutex this against handlePacket().
-     */
-    ssize_t actual;
-    actual = writev(netState->clientSock, iov, iovcnt);
+    ssize_t actual = netState->writeBufferedPacket(iov, iovcnt);
+
     if ((size_t)actual != expected) {
-        LOGE("Failed sending b-req to debugger: %s (%d of %zu)\n",
+        ALOGE("Failed sending b-req to debugger: %s (%d of %zu)",
             strerror(errno), (int) actual, expected);
         return false;
     }