summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2014-11-27 17:10:45 +0000
committerNeil Fuller <nfuller@google.com>2014-11-28 09:25:03 +0000
commit1791f6be1bd2733babb0c862ad8509f4c847b48f (patch)
tree942fdd30ceb6563de11d318cc2a54c53755300d1
parent9250fd718bd449cab13681cbc2b31bf65569d31f (diff)
downloadlibcore-1791f6be1bd2733babb0c862ad8509f4c847b48f.zip
libcore-1791f6be1bd2733babb0c862ad8509f4c847b48f.tar.gz
libcore-1791f6be1bd2733babb0c862ad8509f4c847b48f.tar.bz2
Fix crash in selector.wakeup() with closed selector
Selector.wakeup() can throw an undeclared IOException (from native code). This is not compatible with the signature of wakeup(). In prior Android releases no exception is thrown in this case. This change reverts the behavior to the same as prior Android releases. Many thanks to diddysbestbud@ for the report. Bug: https://code.google.com/p/android/issues/detail?id=80785 Bug: 18548071 Change-Id: I5421e8a0ae1fdf2cde9cb635dae56b4fd02b6ac4
-rw-r--r--luni/src/main/java/android/system/Os.java16
-rw-r--r--luni/src/main/java/libcore/io/ForwardingOs.java2
-rw-r--r--luni/src/main/java/libcore/io/Os.java2
-rw-r--r--luni/src/main/java/libcore/io/Posix.java2
-rw-r--r--luni/src/main/native/libcore_io_Posix.cpp47
-rw-r--r--luni/src/test/java/libcore/java/nio/channels/SelectorTest.java63
6 files changed, 62 insertions, 70 deletions
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 0b80b52..9d6dc1b 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -16,20 +16,6 @@
package android.system;
-import android.system.ErrnoException;
-import android.system.GaiException;
-import android.system.StructAddrinfo;
-import android.system.StructFlock;
-import android.system.StructGroupReq;
-import android.system.StructGroupSourceReq;
-import android.system.StructLinger;
-import android.system.StructPasswd;
-import android.system.StructPollfd;
-import android.system.StructStat;
-import android.system.StructStatVfs;
-import android.system.StructTimeval;
-import android.system.StructUcred;
-import android.system.StructUtsname;
import android.util.MutableInt;
import android.util.MutableLong;
import java.io.FileDescriptor;
@@ -125,7 +111,7 @@ public final class Os {
/** @hide */ public static int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return Libcore.os.fcntlVoid(fd, cmd); }
/** @hide */ public static int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException { return Libcore.os.fcntlLong(fd, cmd, arg); }
- /** @hide */ public static int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException { return Libcore.os.fcntlFlock(fd, cmd, arg); }
+ /** @hide */ public static int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return Libcore.os.fcntlFlock(fd, cmd, arg); }
/**
* See <a href="http://man7.org/linux/man-pages/man2/fdatasync.2.html">fdatasync(2)</a>.
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index bf4b448..584fd58 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -67,7 +67,7 @@ public class ForwardingOs implements Os {
public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException { os.fchown(fd, uid, gid); }
public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return os.fcntlVoid(fd, cmd); }
public int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException { return os.fcntlLong(fd, cmd, arg); }
- public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException { return os.fcntlFlock(fd, cmd, arg); }
+ public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return os.fcntlFlock(fd, cmd, arg); }
public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); }
public StructStat fstat(FileDescriptor fd) throws ErrnoException { return os.fstat(fd); }
public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException { return os.fstatvfs(fd); }
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 511bb27..9f080a6 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -58,7 +58,7 @@ public interface Os {
public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException;
public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException;
public int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException;
- public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
+ public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException;
public void fdatasync(FileDescriptor fd) throws ErrnoException;
public StructStat fstat(FileDescriptor fd) throws ErrnoException;
public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index f5eaaa3..cab67e8 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -61,7 +61,7 @@ public final class Posix implements Os {
public native void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException;
public native int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException;
public native int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException;
- public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
+ public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException;
public native void fdatasync(FileDescriptor fd) throws ErrnoException;
public native StructStat fstat(FileDescriptor fd) throws ErrnoException;
public native StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index e8e8efb..7e9b22e 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -127,32 +127,27 @@ struct addrinfo_deleter {
*/
#define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
return_type _rc = -1; \
- int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
- if (_fd == -1) { \
- jniThrowException(jni_env, "java/io/IOException", "File descriptor closed"); \
- } else { \
- do { \
- bool _wasSignaled; \
- int _syscallErrno; \
- { \
- int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
- AsynchronousCloseMonitor _monitor(_fd); \
- _rc = syscall_name(_fd, __VA_ARGS__); \
- _syscallErrno = errno; \
- _wasSignaled = _monitor.wasSignaled(); \
- } \
- if (_wasSignaled) { \
- jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \
- _rc = -1; \
- break; \
- } \
- if (_rc == -1 && _syscallErrno != EINTR) { \
- /* TODO: with a format string we could show the arguments too, like strace(1). */ \
- throwErrnoException(jni_env, # syscall_name); \
- break; \
- } \
- } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
- } \
+ do { \
+ bool _wasSignaled; \
+ int _syscallErrno; \
+ { \
+ int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
+ AsynchronousCloseMonitor _monitor(_fd); \
+ _rc = syscall_name(_fd, __VA_ARGS__); \
+ _syscallErrno = errno; \
+ _wasSignaled = _monitor.wasSignaled(); \
+ } \
+ if (_wasSignaled) { \
+ jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \
+ _rc = -1; \
+ break; \
+ } \
+ if (_rc == -1 && _syscallErrno != EINTR) { \
+ /* TODO: with a format string we could show the arguments too, like strace(1). */ \
+ throwErrnoException(jni_env, # syscall_name); \
+ break; \
+ } \
+ } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
_rc; })
static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
diff --git a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
index c5f449e..9789197 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -146,32 +146,43 @@ public class SelectorTest extends TestCase {
}
public void test_57456() throws Exception {
- Selector selector = Selector.open();
- ServerSocketChannel ssc = ServerSocketChannel.open();
-
- try {
- // Connect.
- ssc.configureBlocking(false);
- ssc.socket().bind(null);
- SocketChannel sc = SocketChannel.open();
- sc.connect(ssc.socket().getLocalSocketAddress());
- sc.finishConnect();
-
- // Switch to non-blocking so we can use a Selector.
- sc.configureBlocking(false);
-
- // Have the 'server' write something.
- ssc.accept().write(ByteBuffer.allocate(128));
-
- // At this point, the client should be able to read or write immediately.
- // (It shouldn't be able to connect because it's already connected.)
- SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
- assertEquals(1, selector.select());
- assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps());
- assertEquals(0, selector.select());
- } finally {
+ Selector selector = Selector.open();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+
+ try {
+ // Connect.
+ ssc.configureBlocking(false);
+ ssc.socket().bind(null);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(ssc.socket().getLocalSocketAddress());
+ sc.finishConnect();
+
+ // Switch to non-blocking so we can use a Selector.
+ sc.configureBlocking(false);
+
+ // Have the 'server' write something.
+ ssc.accept().write(ByteBuffer.allocate(128));
+
+ // At this point, the client should be able to read or write immediately.
+ // (It shouldn't be able to connect because it's already connected.)
+ SelectionKey key = sc.register(selector,
+ SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ assertEquals(1, selector.select());
+ assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps());
+ assertEquals(0, selector.select());
+ } finally {
+ selector.close();
+ ssc.close();
+ }
+ }
+
+ // http://code.google.com/p/android/issues/detail?id=80785
+ public void test_80785() throws Exception {
+ Selector selector = Selector.open();
selector.close();
- ssc.close();
- }
+
+ // Historically on android this did not throw an exception. Due to the bug it would throw
+ // an (undeclared) IOException.
+ selector.wakeup();
}
}