From c390acc2461cce9edb3209caca28d95ed6aabd90 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 7 Sep 2010 12:00:00 -0700 Subject: [PATCH] Don't throw when calling Socket.close on a closed socket. Bug: 2980559 Change-Id: I168573c16581a3a94b96f0ccdb458bfee76f11e0 --- dalvik/src/main/java/dalvik/system/BlockGuard.java | 22 ++++++++++++++++------ .../src/test/java/libcore/java/net/SocketTest.java | 8 ++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java index a7d14f47..ba49da76 100644 --- a/dalvik/src/main/java/dalvik/system/BlockGuard.java +++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java @@ -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()); } } } diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java index 7646ddcf..f769a45f 100644 --- a/luni/src/test/java/libcore/java/net/SocketTest.java +++ b/luni/src/test/java/libcore/java/net/SocketTest.java @@ -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 -- 2.11.0