OSDN Git Service

Don't throw when calling Socket.close on a closed socket.
authorElliott Hughes <enh@google.com>
Tue, 7 Sep 2010 19:00:00 +0000 (12:00 -0700)
committerElliott Hughes <enh@google.com>
Tue, 7 Sep 2010 20:19:27 +0000 (13:19 -0700)
Bug: 2980559
Change-Id: I168573c16581a3a94b96f0ccdb458bfee76f11e0

dalvik/src/main/java/dalvik/system/BlockGuard.java
luni/src/test/java/libcore/java/net/SocketTest.java

index a7d14f4..ba49da7 100644 (file)
@@ -383,6 +383,9 @@ public final class BlockGuard {
         }
 
         public void close(FileDescriptor aFD) throws IOException {
+            // We exclude sockets without SO_LINGER so that apps can close their network connections
+            // in methods like onDestroy, which will run on the UI thread, without jumping through
+            // extra hoops.
             if (isLingerSocket(aFD)) {
                 BlockGuard.getThreadPolicy().onNetwork();
             }
@@ -394,13 +397,20 @@ public final class BlockGuard {
         }
 
         private boolean isLingerSocket(FileDescriptor fd) throws SocketException {
-            Object lingerValue = mNetwork.getSocketOption(fd, SocketOptions.SO_LINGER);
-            if (lingerValue instanceof Boolean) {
-                return (Boolean) lingerValue;
-            } else if (lingerValue instanceof Integer) {
-                return ((Integer) lingerValue) != 0;
+            try {
+                Object lingerValue = mNetwork.getSocketOption(fd, SocketOptions.SO_LINGER);
+                if (lingerValue instanceof Boolean) {
+                    return (Boolean) lingerValue;
+                } else if (lingerValue instanceof Integer) {
+                    return ((Integer) lingerValue) != 0;
+                }
+                throw new AssertionError(lingerValue.getClass().getName());
+            } catch (Exception ignored) {
+                // We're called via Socket.close (which doesn't ask for us to be called), so we
+                // must not throw here, because Socket.close must not throw if asked to close an
+                // already-closed socket.
+                return false;
             }
-            throw new AssertionError(lingerValue.getClass().getName());
         }
     }
 }
index 7646ddc..f769a45 100644 (file)
@@ -31,6 +31,14 @@ import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 
 public class SocketTest extends junit.framework.TestCase {
+    // See http://b/2980559.
+    public void test_close() throws Exception {
+        Socket s = new Socket();
+        s.close();
+        // Closing a closed socket does nothing.
+        s.close();
+    }
+
     /**
      * Our getLocalAddress and getLocalPort currently use getsockname(3).
      * This means they give incorrect results on closed sockets (as well