summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2014-08-15 09:56:53 -0700
committerElliott Hughes <enh@google.com>2014-08-15 10:43:19 -0700
commit88ea8271db2936989654f50af16737b2323f27ac (patch)
treec7ab54701323e9fa5f8a082350b355558cee0d4d
parenta6bb8774bf6ef792eb4af227b135b6cad815a1e3 (diff)
downloadlibcore-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.java7
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