diff options
author | Elliott Hughes <enh@google.com> | 2014-08-15 09:56:53 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2014-08-15 10:43:19 -0700 |
commit | 88ea8271db2936989654f50af16737b2323f27ac (patch) | |
tree | c7ab54701323e9fa5f8a082350b355558cee0d4d | |
parent | a6bb8774bf6ef792eb4af227b135b6cad815a1e3 (diff) | |
download | libcore-88ea8271db2936989654f50af16737b2323f27ac.zip libcore-88ea8271db2936989654f50af16737b2323f27ac.tar.gz libcore-88ea8271db2936989654f50af16737b2323f27ac.tar.bz2 |
Avoid triggering StrictMode when closing a socket.
Originally, we called getsockoptLinger unconditionally, using ENOTSOCK
to recognize the non-socket case, but the cost of throwing an exception
is so high (both on dalvik and art) that we worked around that by doing
an fstat first. This was mostly fine, but fstat calls onReadFromDisk,
which isn't true for the socket case (which causes upset for threads
that are allowed to touch the network but not allowed to touch disk,
which Chrome uses, even though it's not immediately obvious to me why
that makes any sense).
(cherry-pick of d636777d624428dfc51d1181f47602f389eb4cce.)
Bug: 4972558
Bug: 12133112
Change-Id: Ic0b89d1f181e436b4f43c1c04c1f706883ab84c0
-rw-r--r-- | luni/src/main/java/libcore/io/BlockGuardOs.java | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java index 0b04e2b..764e60a 100644 --- a/luni/src/main/java/libcore/io/BlockGuardOs.java +++ b/luni/src/main/java/libcore/io/BlockGuardOs.java @@ -31,6 +31,7 @@ import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import static android.system.OsConstants.*; +import static dalvik.system.BlockGuard.DISALLOW_NETWORK; /** * Informs BlockGuard of any activity it should be aware of. @@ -79,15 +80,17 @@ public class BlockGuardOs extends ForwardingOs { @Override public void close(FileDescriptor fd) throws ErrnoException { try { - if (S_ISSOCK(Libcore.os.fstat(fd).st_mode)) { + // The usual case is that this _isn't_ a socket, so getsockopt will throw, + // and that's really expensive. Try to avoid asking if we don't care. + if ((BlockGuard.getThreadPolicy().getPolicyMask() & DISALLOW_NETWORK) != 0) { if (isLingerSocket(fd)) { // If the fd is a socket with SO_LINGER set, we might block indefinitely. // We allow non-linger sockets so that apps can close their network // connections in methods like onDestroy which will run on the UI thread. BlockGuard.getThreadPolicy().onNetwork(); } - untagSocket(fd); } + untagSocket(fd); } catch (ErrnoException 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 |