summaryrefslogtreecommitdiffstats
path: root/luni/src
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2014-12-15 16:14:56 -0800
committerElliott Hughes <enh@google.com>2014-12-17 10:16:23 -0800
commitfa542091e45db699a937c5ac0191194405107827 (patch)
treea09af98504fb8287e825fa96778d7df481eb4caa /luni/src
parentae5e913146e8840b1e692f92299473268f90f415 (diff)
downloadlibcore-fa542091e45db699a937c5ac0191194405107827.zip
libcore-fa542091e45db699a937c5ac0191194405107827.tar.gz
libcore-fa542091e45db699a937c5ac0191194405107827.tar.bz2
Fix poll to never return EINTR.
Bug: 18759467 Change-Id: Ia5b97a55318b5990ad6b80d15641223aa4fb06f5
Diffstat (limited to 'luni/src')
-rw-r--r--luni/src/main/java/android/system/Os.java4
-rw-r--r--luni/src/main/java/java/nio/SelectorImpl.java5
-rw-r--r--luni/src/main/java/libcore/io/IoBridge.java6
-rw-r--r--luni/src/main/native/libcore_io_Posix.cpp64
-rw-r--r--luni/src/test/java/libcore/java/nio/channels/SelectorTest.java21
5 files changed, 56 insertions, 44 deletions
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 7f73a85..2626685 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -308,6 +308,10 @@ public final class Os {
/**
* See <a href="http://man7.org/linux/man-pages/man2/poll.2.html">poll(2)</a>.
+ *
+ * <p>Note that in Lollipop this could throw an {@code ErrnoException} with {@code EINTR}.
+ * In later releases, the implementation will automatically just restart the system call with
+ * an appropriately reduced timeout.
*/
public static int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException { return Libcore.os.poll(fds, timeoutMs); }
diff --git a/luni/src/main/java/java/nio/SelectorImpl.java b/luni/src/main/java/java/nio/SelectorImpl.java
index 5e2a2b1..c73ba22 100644
--- a/luni/src/main/java/java/nio/SelectorImpl.java
+++ b/luni/src/main/java/java/nio/SelectorImpl.java
@@ -38,7 +38,6 @@ import libcore.io.IoBridge;
import libcore.io.IoUtils;
import libcore.io.Libcore;
-import static android.system.OsConstants.EINTR;
import static android.system.OsConstants.POLLERR;
import static android.system.OsConstants.POLLHUP;
import static android.system.OsConstants.POLLIN;
@@ -183,9 +182,7 @@ final class SelectorImpl extends AbstractSelector {
try {
rc = Libcore.os.poll(pollFds.array(), (int) timeout);
} catch (ErrnoException errnoException) {
- if (errnoException.errno != EINTR) {
- throw errnoException.rethrowAsIOException();
- }
+ throw errnoException.rethrowAsIOException();
}
} finally {
if (isBlocking) {
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index acc8d4f..fcb30dd 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -225,11 +225,7 @@ public final class IoBridge {
if (!fd.valid()) {
throw new SocketException("Socket closed");
}
- if (errnoException.errno == EINTR) {
- return false; // Punt and ask the caller to try again.
- } else {
- cause = errnoException;
- }
+ cause = errnoException;
}
String detail = connectDetail(inetAddress, port, timeoutMs, cause);
if (cause.errno == ETIMEDOUT) {
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 57ff794..c585fc5 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -551,7 +551,7 @@ static void Posix_execve(JNIEnv* env, jobject, jstring javaFilename, jobjectArra
ExecStrings argv(env, javaArgv);
ExecStrings envp(env, javaEnvp);
- execve(path.c_str(), argv.get(), envp.get());
+ TEMP_FAILURE_RETRY(execve(path.c_str(), argv.get(), envp.get()));
throwErrnoException(env, "execve");
}
@@ -563,7 +563,7 @@ static void Posix_execv(JNIEnv* env, jobject, jstring javaFilename, jobjectArray
}
ExecStrings argv(env, javaArgv);
- execv(path.c_str(), argv.get());
+ TEMP_FAILURE_RETRY(execv(path.c_str(), argv.get()));
throwErrnoException(env, "execv");
}
@@ -724,15 +724,15 @@ static jobjectArray Posix_android_getaddrinfo(JNIEnv* env, jobject, jstring java
}
static jint Posix_getegid(JNIEnv*, jobject) {
- return getegid();
+ return TEMP_FAILURE_RETRY(getegid());
}
static jint Posix_geteuid(JNIEnv*, jobject) {
- return geteuid();
+ return TEMP_FAILURE_RETRY(geteuid());
}
static jint Posix_getgid(JNIEnv*, jobject) {
- return getgid();
+ return TEMP_FAILURE_RETRY(getgid());
}
static jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) {
@@ -764,11 +764,11 @@ static jobject Posix_getpeername(JNIEnv* env, jobject, jobject javaFd) {
}
static jint Posix_getpid(JNIEnv*, jobject) {
- return getpid();
+ return TEMP_FAILURE_RETRY(getpid());
}
static jint Posix_getppid(JNIEnv*, jobject) {
- return getppid();
+ return TEMP_FAILURE_RETRY(getppid());
}
static jobject Posix_getpwnam(JNIEnv* env, jobject, jstring javaName) {
@@ -867,14 +867,14 @@ static jint Posix_gettid(JNIEnv* env __unused, jobject) {
}
return static_cast<jint>(owner);
#elif defined(__BIONIC__)
- return gettid();
+ return TEMP_FAILURE_RETRY(gettid());
#else
return syscall(__NR_gettid);
#endif
}
static jint Posix_getuid(JNIEnv*, jobject) {
- return getuid();
+ return TEMP_FAILURE_RETRY(getuid());
}
static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) {
@@ -1088,7 +1088,40 @@ static jint Posix_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint time
for (size_t i = 0; i < count; ++i) {
monitors.push_back(new AsynchronousCloseMonitor(fds[i].fd));
}
- int rc = poll(fds.get(), count, timeoutMs);
+
+ int rc;
+ while (true) {
+ timespec before;
+ clock_gettime(CLOCK_MONOTONIC, &before);
+
+ rc = poll(fds.get(), count, timeoutMs);
+ if (rc >= 0 || errno != EINTR) {
+ break;
+ }
+
+ // We got EINTR. Work out how much of the original timeout is still left.
+ if (timeoutMs > 0) {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ timespec diff;
+ diff.tv_sec = now.tv_sec - before.tv_sec;
+ diff.tv_nsec = now.tv_nsec - before.tv_nsec;
+ if (diff.tv_nsec < 0) {
+ --diff.tv_sec;
+ diff.tv_nsec += 1000000000;
+ }
+
+ jint diffMs = diff.tv_sec * 1000 + diff.tv_nsec / 1000000;
+ if (diffMs >= timeoutMs) {
+ rc = 0; // We have less than 1ms left anyway, so just time out.
+ break;
+ }
+
+ timeoutMs -= diffMs;
+ }
+ }
+
for (size_t i = 0; i < monitors.size(); ++i) {
delete monitors[i];
}
@@ -1115,7 +1148,8 @@ static void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
"fallocate doesn't exist on a Mac");
#else
int fd = jniGetFDFromFileDescriptor(env, javaFd);
- errno = TEMP_FAILURE_RETRY(posix_fallocate64(fd, offset, length));
+ while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) {
+ }
if (errno != 0) {
throwErrnoException(env, "posix_fallocate");
}
@@ -1128,9 +1162,11 @@ static jint Posix_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 _
jniThrowException(env, "java/lang/UnsupportedOperationException", "prctl doesn't exist on a Mac");
return 0;
#else
- int result = prctl(static_cast<int>(option),
- static_cast<unsigned long>(arg2), static_cast<unsigned long>(arg3),
- static_cast<unsigned long>(arg4), static_cast<unsigned long>(arg5));
+ int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option),
+ static_cast<unsigned long>(arg2),
+ static_cast<unsigned long>(arg3),
+ static_cast<unsigned long>(arg4),
+ static_cast<unsigned long>(arg5)));
return throwIfMinusOne(env, "prctl", result);
#endif
}
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 9789197..41b434d 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -15,7 +15,6 @@
*/
package libcore.java.nio.channels;
-import android.system.OsConstants;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -28,7 +27,6 @@ import java.nio.channels.SocketChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
-import libcore.io.Libcore;
import tests.net.StuckServer;
public class SelectorTest extends TestCase {
@@ -71,25 +69,6 @@ public class SelectorTest extends TestCase {
}
}
- // http://b/6453247
- // This test won't work on the host until/unless we start using libcorkscrew there.
- // The runtime itself blocks SIGQUIT, so that doesn't cause poll(2) to EINTR directly.
- // The EINTR is caused by the way libcorkscrew works.
- public void testEINTR() throws Exception {
- Selector selector = Selector.open();
- new Thread(new Runnable() {
- @Override public void run() {
- try {
- Thread.sleep(2000);
- Libcore.os.kill(Libcore.os.getpid(), OsConstants.SIGQUIT);
- } catch (Exception ex) {
- fail();
- }
- }
- }).start();
- assertEquals(0, selector.select());
- }
-
// http://code.google.com/p/android/issues/detail?id=15388
public void testInterrupted() throws IOException {
Selector selector = Selector.open();