Skip writing PFD status when comm is closed.
If the remote side of PFD has already written a status message, then
they've also closed their end of the comm FD, and we're going to
EPIPE if we try sending our own status. So, skip writing status if
a remote status is present.
Only one end of the openFile() comm socket needs to be blocking,
otherwise detachFd() would end up blocking forever.
Bug: 11385467
Change-Id: I346d40cc1ca4a6683cec4c2d2b7db2b32ac94a55
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 1456387..5273c20 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -231,10 +231,11 @@
final FileDescriptor fd = openInternal(file, mode);
if (fd == null) return null;
- final FileDescriptor[] comm = createCommSocketPair(true);
+ final FileDescriptor[] comm = createCommSocketPair();
final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]);
// Kick off thread to watch for status updates
+ IoUtils.setBlocking(comm[1], true);
final ListenerBridge bridge = new ListenerBridge(comm[1], handler.getLooper(), listener);
bridge.start();
@@ -378,7 +379,7 @@
*/
public static ParcelFileDescriptor[] createReliablePipe() throws IOException {
try {
- final FileDescriptor[] comm = createCommSocketPair(false);
+ final FileDescriptor[] comm = createCommSocketPair();
final FileDescriptor[] fds = Libcore.os.pipe();
return new ParcelFileDescriptor[] {
new ParcelFileDescriptor(fds[0], comm[0]),
@@ -416,7 +417,7 @@
*/
public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException {
try {
- final FileDescriptor[] comm = createCommSocketPair(false);
+ final FileDescriptor[] comm = createCommSocketPair();
final FileDescriptor fd0 = new FileDescriptor();
final FileDescriptor fd1 = new FileDescriptor();
Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
@@ -428,13 +429,13 @@
}
}
- private static FileDescriptor[] createCommSocketPair(boolean blocking) throws IOException {
+ private static FileDescriptor[] createCommSocketPair() throws IOException {
try {
final FileDescriptor comm1 = new FileDescriptor();
final FileDescriptor comm2 = new FileDescriptor();
Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
- IoUtils.setBlocking(comm1, blocking);
- IoUtils.setBlocking(comm2, blocking);
+ IoUtils.setBlocking(comm1, false);
+ IoUtils.setBlocking(comm2, false);
return new FileDescriptor[] { comm1, comm2 };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
@@ -670,34 +671,35 @@
}
try {
+ if (status == Status.SILENCE) return;
+
+ // Since we're about to close, read off any remote status. It's
+ // okay to remember missing here.
+ mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
+
+ // Skip writing status when other end has already gone away.
+ if (mStatus != null) return;
+
try {
- if (status != Status.SILENCE) {
- final byte[] buf = getOrCreateStatusBuffer();
- int writePtr = 0;
+ final byte[] buf = getOrCreateStatusBuffer();
+ int writePtr = 0;
- Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
- writePtr += 4;
+ Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
+ writePtr += 4;
- if (msg != null) {
- final byte[] rawMsg = msg.getBytes();
- final int len = Math.min(rawMsg.length, buf.length - writePtr);
- System.arraycopy(rawMsg, 0, buf, writePtr, len);
- writePtr += len;
- }
-
- Libcore.os.write(mCommFd, buf, 0, writePtr);
+ if (msg != null) {
+ final byte[] rawMsg = msg.getBytes();
+ final int len = Math.min(rawMsg.length, buf.length - writePtr);
+ System.arraycopy(rawMsg, 0, buf, writePtr, len);
+ writePtr += len;
}
+
+ Libcore.os.write(mCommFd, buf, 0, writePtr);
} catch (ErrnoException e) {
// Reporting status is best-effort
Log.w(TAG, "Failed to report status: " + e);
}
- if (status != Status.SILENCE) {
- // Since we're about to close, read off any remote status. It's
- // okay to remember missing here.
- mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
- }
-
} finally {
IoUtils.closeQuietly(mCommFd);
mCommFd = null;